Understanding this JavaScript Overload Example

I am currently learning John Resig Ninja JavaScript Secrets , and I hope someone can help me understand one example.

This is a function that allows method overloading on an object, each overload has its own definition and behavior. He wrote about it here .

The code is as follows:

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

And used like this:

 addMethod(obj,'funcName',function(){}); addMethod(obj,'funcName',function(a){}); addMethod(obj,'funcName',function(a,b){}); 

I think I understand most of how this works, but you can get a better explanation than I can give from the blog post above).

However, it accesses the value of old and fn with closures, which I am still studying.

EDIT - added by jsFiddle below.

While trying to figure this out, I realized that returning the string fn.apply(this, arguments) might just be return fn() with what looks like the same result. See an example in jsFiddle .

So why does it use apply syntax if it is not required?

I tried playing with an example in jsFiddle without applying and it always seems wo

Also, what exactly happens when we return these functions, especially in the case of:

 return old.apply(this, arguments); 

I really want to get a clear idea of ​​how to use this method, but why it works, so any understanding will be appreciated.

thanks

+4
source share
6 answers

So why does it use apply syntax if not required?

It is really necessary to use.

this and arguments different for each function and are set when they are called. Using fn() , fn will be called with an empty arguments collection or with no value for this .

.apply(this, arguments) calls fn or old and passes values ​​at the current value of function .

 var obj = {}; addMethod(obj, 'funcName', function (a, b) { console.log(this === obj); console.log(a, b); console.log(arguments[0], arguments[1]); }); obj.funcName(2, 3); // true // 2, 3 // 2, 3 

Also, what exactly happens when we return these functions, especially in the case of:

 return old.apply(this, arguments); 

Well, the purpose of addMethod is to create a chain of functions where everyone knows and can call the old function created before it.

In the example from the book, the chain is built as:

 // after: addMethod(obj, 'funcName', function(){}); obj.funcName = function(){...} ──> function(){} 
 // after: addMethod(obj, 'funcName', function(a){}); obj.funcName = function(){...} ──────> function(a){} └── function(){...} ──> function(){} 
 // after: addMethod(obj, 'funcName', function(a,b){}); obj.funcName = function(){...} ──────────> function(a,b){} └── function(){...} ──────> function(a){} └── function(){...} ──> function(){} 
 Legend: `└──` represents an `old` reference `──>` represents a `fn` reference 

Each function(){...} is a unique instance created by re-evaluating the same expression in a different scope / closure:

 function(){ if (fn.length == arguments.length) return fn.apply(this, arguments) else if (typeof old == 'function') return old.apply(this, arguments); } 

Each .apply() then follows the β€œhand” or β€œarrow” either with the old or fn , and return allows the result to be passed back / back.

+3
source

I think you are missing the .apply point

I will not try to explain this: P you can find many good explanations, for example:

TL; dg

.apply allows .apply to set this context. .apply allows .apply to pass arguments as an array, allowing a variable number of arguments.

+1
source

In Javascript, the this variable is not set at the time the function is declared, but at the time of its execution, depending on which object was used to access the function reference.

You need to use apply not only because of the aforementioned dynamic binding of this , but also because you don't know how many arguments are in front of you; therefore, apply receives a list of arguments and passes each element of the list as a separate argument to the function.

+1
source

With .apply you can specify the context

 window.name = "window"; var object = { name:"object" }; function showName(){ alert(this.name); } showName(); // shows window showName.apply(object); // shows object 

here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

+1
source

Here is a breakdown of the code.

 function addMethod(object, name, fn) { //get the old function from the object var old = object[name]; //assign a new function to the property object[name] = function(){ //See if the method signatures match, if they do execute the new method if (fn.length == arguments.length) /* Call the function provided using apply, the first argument "this" is the object it sets the context for this in the function we provide, second argument is the arguments provided to the function. We must return the result of the function. */ return fn.apply(this, arguments) //If the old property on the object is a function and the new functions signature //did not match call the old function assigned to the property. else if (typeof old == 'function') // Same as before calling with apply, setting context and returning result return old.apply(this, arguments); }; 

It is important to understand how apply works. It sets the context for this inside the function. For instance:

 var myFunction = function(){ alert(this.msg); //this will be set by what apply passes in as the first arg }; var obj1 = {msg: "Hello"}; var obj2 = {msg: "World"}; myFunction.apply(obj1); myFunction.apply(obj2); 

Example http://jsfiddle.net/NCaKX/

+1
source
 fn.apply(this, arguments) 

calls fn with this as current this and arguments as parameters.

 fn() 

calls fn with this equal to window or undefined (depending on whether you are in "non-line mode" or "in strict mode"), but without parameters.

This Mozilla.org page has a good discussion on this (always helpful)

0
source

Source: https://habr.com/ru/post/1495912/


All Articles