Jump to content
Sign in to follow this  
abdelelbouhy

function overloading

Recommended Posts

Hi guys,

can you please explain how this code is working i'm a bit confuse about the fn.length == arguments.length here the code

 

function addMethod(object, name, fn) {
var old = object[name];
object[name] = function(){
if (fn.length == arguments.length){ //this line i don't understand how it works
return fn.apply(this, arguments)
}else if (typeof old == 'function'){
return old.apply(this, arguments);
}
};
}
var ninjas = {
values: ["Dean Edwards", "Sam Stephenson", "Alex Russell"]
};
addMethod(ninjas, "find", function(){
return this.values;
});
addMethod(ninjas, "find", function(name){
var ret = [];
for (var i = 0; i < this.values.length; i++)
if (this.values.indexOf(name) == 0)
ret.push(this.values);
return ret;
});
addMethod(ninjas, "find", function(first, last){
var ret = [];
for (var i = 0; i < this.values.length; i++)
if (this.values == (first + " " + last))
ret.push(this.values);
return ret;
});
when you call addMethod the first time fn.length == arguments.length is true both are zero that's fine then it execute return fn.apply(this, arguments)
the second and third fn.length is 1 then 2 but arguments.length is 0 because no args passed to the anonymous function and it should execute return old.apply(this, arguments); but what happened it execute the first condition so how comes it execute this line even if the lengths are not equal
Edited by abdelelbouhy

Share this post


Link to post
Share on other sites

if you are asking for a code review, (and not to be rude) would be to at least provide the code in the most readable way possible. That would include indented code and posted within [ code ] tags.

Edited by thescientist

Share this post


Link to post
Share on other sites

Sorry mate i fixed the indent my question is how the code calls different functions even if the arguments length is always 0 or i'm missing something

Edited by abdelelbouhy

Share this post


Link to post
Share on other sites

If you're asking about Function.length, here's what it means:

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length

 

arguments is a variable that is automatically defined in any function, it is the list of arguments that were actually passed to the function. So they are checking if the number of arguments that were actually passed to the function is the same number of arguments that the function expects. It's basically a hack to implement the concept of function overloading that other languages support, where you can define different functions with the same name but different parameter lists, and it will execute the function based on what parameters you pass. arguments.length is not always 0 inside the anonymous function, arguments is the list of actual arguments that were passed. If you call ninjas.find with 2 arguments, it's going to run the function that has 2 arguments defined. It's a weird but clever recursive hack to implement something like function overloading.

Share this post


Link to post
Share on other sites

Thank you very much now start to clear it a bit one more thing how the arguments inside the clouser refer to the function that is passed as the argument to the outer function shouldn't arguments inside the inner refer to the arguments of the inner function

Edited by abdelelbouhy

Share this post


Link to post
Share on other sites

There are several functions here, which aren't always obvious. When you do this:

 

 

 

addMethod(ninjas, "find", function(first, last){            var ret = [];            for (var i = 0; i < this.values.length; i++)                  if (this.values[i] == (first + " " + last))                      ret.push(this.values[i]);            return ret;});

 

 

Then inside addMethod:

 

 

 

function addMethod(object, name, fn) {       var old = object[name];       object[name] = function(){             if (fn.length == arguments.length){ //this line i don't understand how it works                    return fn.apply(this, arguments)              }else if (typeof old == 'function'){                    return old.apply(this, arguments);              }        };}

 

fn is set to the anonymous function that was passed, the one with 2 parameters defined. So, it redefines object[name], which evaluates to ninja.find, as a new anonymous function after saving the old function. Saving the old function makes a closure where every function you pass to addMethod is basically queued up, that's where the recursion comes in. That anonymous function that gets set as ninja.find gets defined several times, once for each call, and they end up in closures. So if you call ninja.find and don't pass any parameters, it's going to execute the anonymous function defined on 2 parameters first, see that the parameter count doesn't match, and then execute old, which is going to be the function that was defined for one parameter, see that the parameters don't match either, and call old again, which is going to be the function defined for no parameters. So it's like a recursive closure stack. But if you call ninja.find and pass 2 parameters, you are calling the anonymous function defined in addMethod. That's the function that you pass the parameters to, so that's what arguments contains. If it finds that fn.length is the same as the number of parameters that was passed, then it calls fn in the same scope and passes it the same arguments that you passed to find (the anonymous function).

 

Hopefully that made sense.

Share this post


Link to post
Share on other sites

Thank you i was trying to figure it out all day but when i call it the last time with 2 parameters var old should have the previous one the one with 1 parameter instead of the one with no parameter because the object property has the same name find it should be overwritten i know you said it queued up all but how is that if the property name is the same

Share this post


Link to post
Share on other sites

They are still in memory and queued up because before they overwrite the function with a new one, they save the old one in the old variable. That variable containing the old function is still in scope when you're executing the new function, so it's still defined there. It's a confusing chain, but it works. It's pretty clever.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...