Friday, August 22, 2014

Method overloading based on John Resig's addMethod

I was reading the book Secrets of the Javascript Ninga and I came accross the addMethod function by +John Resig.

// addMethod - By John Resig (MIT Licensed)
function addMethod(object, name, fn) {
  var old = object[name];
  object[name] = function() {
  if (fn.length == arguments.length)
    return fn.apply(this, arguments);
  else if (typeof old == 'function')
    return old.apply(this, arguments);
  };
}

  This function keeps a pointer to the old method if it exist (via closure) and overwirtes the method with a new one. This new method compares the function length and the arguments length and if they are equal it calls the method provided otherwise it calls the old method.
  So if you add many methods and try to call the one that was added first, it will go through all the methods added and in each it will fall back to the old method because arguments doesn't match the function length, and finally it will land on the first added.

  I made an alternative to this function.

// addMethod - By Stavros Ioannidis
function addMethod(obj, name, fn) {
  obj[name] = obj[name] || function() {
    // get the cached method with arguments.length arguments
    var method = obj[name].cache[arguments.length];

    // if method exists call it 
    if ( !! method)
      return method.apply(this, arguments);
    else throw new Error("Wrong number of arguments");
  };

  // initialize obj[name].cache
  obj[name].cache = obj[name].cache || {};


  // Check if a method with the same 
  // number of arguments exists  
  if ( !! obj[name].cache[fn.length])
    throw new Error("Cannot define multiple '" + name +
    "' methods with the same number of arguments!");

  // cache the method with fn.length arguments
  obj[name].cache[fn.length] = function() {
   return fn.apply(this, arguments);
  };
}

This 'addMethod' keeps a cache of the added methods using fn.length as the key, and it calls directly the one whose key matches the arguments.length.
I think this might be slightly faster than John's function, but there is a cache property on the method which might create problems if it is altered.

No comments:

Post a Comment