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