I'm reading Douglas Crockford's Javascript the good parts,but I can't understand the implemention of Array.push in the chapter 8 Methods,as follows:
Function.prototype.method = function(name,func){
if(!this.prototype[name]){
this.prototype[name] = func;
}
};
Array.method('mypush',function(){
this.splice.apply(this,[this.length,0].concat(Array.prototype.slice.apply(arguments)));
return this.length;
});
var arr = [1,2,3];
arr.mypush(2,3);
console.log(arr);
I can't understand this statement:
this.splice.apply(this,[this.length,0].concat(Array.prototype.slice.apply(arguments)));
Any help would be greatly appreciated, Thanks
2 Answers 2
Do that from the inside out:
Array.prototype.slice.apply(arguments)
--- convertsarguments
array-like object into a real array[this.length,0].concat(#1)
--- concatenates the hardcoded[this.length,0]
array with the array from #1this.splice.apply(this, #2)
--- applies thethis.splice
function tothis
object with arguments from #2
Finally it will look like: this.splice(this.length, 0, arg1, arg2, arg3)
which means: at the index equal to this.length
(see "in the very end) replace 0
elements (see - don't remove anything) with the given arguments.
References:
Comments
apply
takes a function and calls it on the supplied this
object and parameters taken from an array.
this.splice.apply(this,[this.length,0].concat(Array.prototype.slice.apply(arguments)));
So, what we have here is:
this.splice // a reference to the function "splice" that an Array has
this.splice.apply // invoke this function
this.splice.apply(this // invoke it on "this"
this.splice.apply(this,[ // with an array of parameters
[this.length,0] // the first two parameters are "the length", and a "0"
// calling splice this way means replacing the 0 elements
// after the end of the array with the following new elements
// => i.e. pushing the new elements
].concat // but we add some more parameters
Array.prototype.slice.apply(arguments)
// namely the arguments passed into this function
That last step is necessary because arguments
is not a real array, so it does not work with concat. slice
makes a copy of it (into a real array).
Summing it all up with an example.
If you called [1,2,3].mypush(2,3)
it translates into [1,2,3].splice(3, 0, 2, 3)
;