Wednesday, November 14th, 2007

JavaScript Method Overloading

Category: JavaScript

John Resig has posted on JavaScript Method Overloading where he discusses the ability to run different code depending on the number of arguments passed into the same function name. The type of arguments are not considered, which is where JavaScript 2 comes in.

The code he uses:

javascript

  1. // addMethod - By John Resig (MIT Licensed)
  2. function addMethod(object, name, fn){
  3.     var old = object[ name ];
  4.     object[ name ] = function(){
  5.     if ( fn.length == arguments.length )
  6.        return fn.apply( this, arguments );
  7.     else if ( typeof old == 'function' )
  8.        return old.apply( this, arguments );
  9.    };
  10. }
  11.  
  12. // Now setup the methods
  13.  
  14. function Users(){
  15.   addMethod(this, "find", function(){
  16.     // Find all users...
  17.   });
  18.   addMethod(this, "find", function(name){
  19.     // Find a user by name
  20.   });
  21.   addMethod(this, "find", function(first, last){
  22.     // Find a user by first and last name
  23.   });
  24. }
  25.  
  26. // Now use the methods
  27. var users = new Users();
  28. users.find(); // Finds all
  29. users.find("John"); // Finds users by name
  30. users.find("John", "Resig"); // Finds users by first and last name
  31. users.find("John", "E", "Resig"); // Does nothing

John ends with the caveats:

  • The overloading only works for different numbers of arguments – it doesn’t differentiate based on type, argument names, or anything else. (ECMAScript 4/JavaScript 2, however, will have this ability – called Multimethods – I’m quite excited.)
  • All methods will some function call overhead. Thus, you’ll want to take that into consideration in high performance situations.

Now, the secret sauce is all going back to the fn.length expression. This isn’t very well known, but all functions have a length property on them. This property equates to the number of arguments that the function is expecting. Thus, if you define a function that accepts a single argument, it’ll have a length of 1, like so:

(function(foo){}).length == 1

Posted by Dion Almaer at 11:29 am
14 Comments

+++--
3.3 rating from 50 votes

14 Comments »

Comments feed TrackBack URI

This is a pretty cool hack. Its kinda sucks that there has to be so many cool hacks to make Javascript a pretty cool language.

Comment by vance Dubberly — November 14, 2007

Why is this necessary? You can simply make a function called “find” and access the arguments array from within. Then do some switch logic internally on either the number of arguments, or by type and then do your stuff. Also, it is often much more convenient to have a method take an “anonymous object” and pass parameters by name such as this…

find({first:”Jim”,last:”bob”}); or find({name:”Jim Bob”})

Named parameters is something I really miss in C# development! I think Javascript is incredibly flexible, doesn’t require “hacks”, but isn’t your traditional OO language either. Both have strengths and weaknesses but most of the time I find overloading in Javascript more flexible, yet terse than C# or Java.

Comment by Jason — November 14, 2007

MooTools has a different approach in 1.2 for various methods. You can pass various argument types. They are not linked by arguments-length but by type, really neat.
Anyway, I think giving an array/object with optional arguments is still the most readable and most consistent way.

Comment by Harald — November 14, 2007

I agree with Jason. This isn’t necessary. Just test the arguments passed in.

Comment by Aaron — November 14, 2007

Resig must dream in JavaScript.

Comment by jake — November 14, 2007

I would be good if the type of arguments could be tested too. But, i think it’s a unecessary complexity.

Comment by Tiago Albineli Motta — November 14, 2007

Yeah, I have to third the opinion that this isn’t necessary. Test the arguments passed in or simply take in an argument object with the various things you need. Its a nice proof of concept, but its not a very JavaScript-y solution.

Comment by Jon Hartmann — November 14, 2007

even when I prefer using a plain object or the Mootools way, it’s a pretty neat hack that shows once again the limitless power of javascript.
thumbs up for John and his crazy ideas.

Comment by gonchuki — November 14, 2007

To those saying “it isn’t necessary just do …”, you miss both the source of this feature and it’s true benefits.

John is trying to approximate Multimethods, which is a feature of languages which have Multiple Dispatch on methods.

What John is doing manually is ideally done automatically by the language based on the method signature (given multiple definitions of the same function with differing signatures).

Multiple dispatch is more commonly done on the type and arity of the arguments rather than their values.

JS2/ES4 looks to be gaining native multimethods (similar in specificiation to those of Perl 6).

Comment by David — November 14, 2007

I’ve used this approach in both Java & Python, and whilst it is handy, it doesn’t *really* solve any problems that couldn’t have been handled in some other usually more elegant way. It also makes it hard to troubleshoot larger scripts, if it isn’t used correctly, in the right situations.
However, it is one of those “nice to have” features :o)

Comment by yoink — November 14, 2007

David – why would you use this over the anonymous object syntax alluded to by Jason (not me) in the second comment, other than to impress people with the fact that it simulates multimethods?

As for those that suggest checking the types, etc. of the arguments being passed in to determine what to do: what kind of mess would that be? You would end up with all sorts of code trying to figure out what to do when really you should be focusing on the task at hand – the anonymous object syntax seems to me the best fit all-around.

But what do I know? Just another opinionated developer… :P

Comment by Jason Bunting — November 15, 2007

Whilst not “best practise” in most common day situations, this kind of information expands knowledge over JavaScript for solving potential future dilema’s. Innability to see useful implementations for nifty snippets, does not render the information useless. ;)
.
Keep em commin!

Comment by Ben — November 15, 2007

Here is the type checking part of it, for those who like this approach:
http://blog.phpbuero.de/?p=17
Have fun John, and keep up the good work!

Comment by Frank Thuerigen — November 18, 2007

Another version with type-checking:

http://www.thetruetribe.com/2008/03/javascript-method-overloading.html

Comment by jdempcy — April 23, 2008

Leave a comment

You must be logged in to post a comment.