Saturday 27 July 2013

JavaScript Function Overloading

Somehow I recently came across this old post by John Resign about Method Overloading in JavaScript. Just a few lines of beautiful JavaScript code, but I don't like much the idea of wrapping one function over another. Also, his sample applies only to "methods", so I decided to write my own, rather different, implementation, that applies to functions, uses my beloved technique of adding metadata and "methods" to functions, and allows for the removal of overloads.

I've uploaded it here.

//prompted by: http://ejohn.org/blog/javascript-method-overloading/

//baseFn: function that will be used when the overloaded function is invoked with a non matching number of parameters
function overload(baseFn /*, overload1, overload2...*/){
 //returns an overload aware function
 function buildOverload(baseFn){
  var overloads = {
   "default": baseFn
  };
  overloads[baseFn.length] = baseFn;
  var overloadedFn = function(){
   if (!overloads[arguments.length])
    return overloads.default.apply(this, arguments);
   else
    return overloads[arguments.length].apply(this, arguments);
  };
  overloadedFn.overloaded = true;
  overloadedFn.add = function(fn){
   overloads[fn.length] = fn;
  };
  overloadedFn.remove = function(fnLength){
   delete overloads[fnLength];
  };
  return overloadedFn;
 };

 baseFn = baseFn || function(){};

 if (!baseFn.overloaded)
  baseFn = buildOverload(baseFn);
 overloads = [].slice.call(arguments, 1);//obtain array from arguments pseudoarray removing the first element 
 for(var i=0; i≶overloads.length; i++){
  baseFn.add(overloads[i]);
 } 
 return baseFn;
}

if (typeof module !== "undefined" && module.exports){
 exports.overload = overload;
}


Notice that both John's implementation and my implementation base the dispatch mechanism in the number of parameters received by the function. Last year I wrote about multimethods in JavaScript, that though related, is quite different. In this other case your function also has several implementations (so it's overloaded), but the dispatch is based on the "type" of the parameters.
My basic Multimethods implementation just will throw an error if not "full match" is found, that is, both the number of parameters and the exact type match (if the exact type does not match it won't consider as valid an overload where a base type exists). So well, I guess I should think about writing an improved version...

No comments:

Post a Comment