Royi Namir
Royi Namir

Reputation: 148524

JavaScript and function overload clarification

I was reading Secrets of the JavaScript Ninja and I saw this code which produces a function overload:

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);
        };
}

function Ninjas()
{
        var ninjas = ["Dean Edwards", "Sam Stephenson", "Alex Russell"];
        // addMethod is defined in Listing 2-28
        addMethod(this, "find", function ()
        {
                return ninjas;
        });
        addMethod(this, "find", function (name)
        {
                var ret = [];
                for(var i = 0; i < ninjas.length; i++)
                if(ninjas[i].indexOf(name) == 0) ret.push(ninjas[i]);
                return ret;
        });
        addMethod(this, "find", function (first, last)
        {
                var ret = [];
                for(var i = 0; i < ninjas.length; i++)
                if(ninjas[i] == (first + " " + last)) ret.push(ninjas[i]);
                return ret;
        });
}

var ninjas = new Ninjas();


assert(ninjas.find().length == 3, "Finds all ninjas");
assert(ninjas.find("Sam").length == 1, "Finds ninjas by first name");
assert(ninjas.find("Dean", "Edwards").length == 1, "Finds ninjas by first and last name");
assert(ninjas.find("Alex", "X", "Russell") == null, "Does nothing");

function assert(a,b)
{
  if (a==true) console.log(b) ; else console("----");
}

As far as I understand, the addMethod always keeps the old value of the function (via closure).

So finally, there is one function which checks a condition, and if it fails, it invokes the old function which in turn does the same thing.

However I don't understand the evaluation of arguments.length (I know the differences between function().length and argument.length).

To which rectangle does arguments refer to?

enter image description here

I tracked it in debugger, and I'm getting confused because at first, the function registers (so arguments.length is 3 [(object, name, fn)], but later it is invoked so now there are another arguments.

How is that working?

JSBin

Upvotes: 5

Views: 241

Answers (1)

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123473

But does arguments refers to : (which rectangle ?)

The 2nd -- object[name] = function ()

arguments will always refer to the object for the inner-most function declaration/expression. The arguments of any outer functions, such as addMethod(object, name, fn), will be shadowed and rendered inaccessible since they all use the same identifier.


It's comparing the number of arguments that were named (fn.length) to the the number of arguments passed in (arguments.length), using the 1st match. So that:

ninjas.find()                       // (0 == 0), uses `function ()`
ninjas.find("Sam")                  // (1 == 1), uses `function (name)`
ninjas.find("Dean", "Edwards")      // (2 == 2), uses `function (first, last)`
ninjas.find("Alex", "X", "Russell") // (? == 3), no match, returns `undefined`

Upvotes: 5

Related Questions