Ok, I'm trying to explain it piece by piece:
Function.prototype.partial = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
var arg = 0;
for (var i = 0; i < args.length && arg < arguments.length; i++) {
if (args[i] === undefined) {
args[i] = arguments[arg++]; //This line is where the confusion is
}
}
return fn.apply(this, args);
};
};
First line:
var fn = this, args = Array.prototype.slice.call(arguments);
This stores the value of this
and the value of arguments
in two variables, because both values would get overriden in the following function block:
return function() {
//inside here arguments will be whatever is passed to this returned function later.
};
The for loop:
var arg = 0;
for (var i = 0; i < args.length && arg < arguments.length; i++) {
}
It will basically loop through all arguments that were passed to the partial
function and exits earlier if arg >= arguments.length
.
if (args[i] === undefined) {
args[i] = arguments[arg++]; //This line is where the confusion is
}
So, if an argument of the args
array is undefined, we replace it with the next argument in the arguments
array. When every arguments are replaced, the original function gets called with the merged arguments array:
return fn.apply(this, args);
Here is how it would work in practice:
function xy(arg1, arg2) {
console.log(arg1 + " / " + arg2);
}
var p1 = xy.partial("foo", undefined);
p1("bar") //"foo / bar"
var p2 = xy.partial(undefined, "bar");
p2("foo") //"foo / bar"
var p3 = xy.partial("foo");
p3("bar") //"foo / undefined" --> because you have to activly pass "undefined" otherwise the arguments array is too short
And last but not least, how this code workes in detail with the example p1 = xy.partial("foo", undefined);
:
//lets call xy.partial("foo", undefined);
Function.prototype.partial = function() {
//fn = xy
//args = ["foo", undefined]
var fn = this, args = Array.prototype.slice.call(arguments);
//return function that is assigned to p1
//lets call p1("bar")
return function() {
//arguments = ["bar"]
var arg = 0;
//for (var i = 0; i < 2 && arg < 1; i++)
for (var i = 0; i < args.length && arg < arguments.length; i++) {
//first iteration:
//args[0] === "foo" -> nothing happend
//second iteration:
//args[1] === undefined -> args[1] = arguments[0] (= "bar"); arg++;
if (args[i] === undefined) {
args[i] = arguments[arg++]; //This line is where the confusion is
}
}
//at this point: args = ["foo", "bar"];
//now just call the function with the merged array
return fn.apply(this, args);
};
};