Reputation: 148524
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?
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?
Upvotes: 5
Views: 241
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 function
s, 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