.apply() allows you to call a function while specifying two different things:
- The value of the
this pointer inside the function call.
- A set of arguments to pass to the function when your source of the arguments is an array.
One will typically use .call() if the number of arguments to pass to the function is known in advance and will typically use .apply() when the number of arguments is not know in advance and thus the arguments are in an array or can be put into an array.
Presumably, slice() in the code example you show is Array.prototype.slice so that code example is grabbing the set of arguments AFTER the first two and putting them into their own array so that they can then be passed to the original function.
The arguments object in Javascript is "array-like". It has a .length property and is zero indexed like an array, but it does not have any array methods on it. So, if you want to use an array method on it like .slice() to copy some elements to a new array, you have to manually specify array methods from the Array prototype rather than directly use .slice() on the arguments object.
So, if you called:
function myFunc(a, b, c, d) {
// four arguments present here
}
_.delay(myFunc, 100, 1, 2, 3, 4);
The inner workings of _.delay() would skip the first two arguments passed to it (because those are for use directly in _.delay() and get just the remaing last four arguments and then pass those to the callback function using .apply().
Here's a working snippet example:
var _ = {};
var slice = Array.prototype.slice;
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function(){
func.apply(null, args);
}, wait);
};
function myFunc() {
log("number of arguments passed to myFunc(): " + arguments.length);
log(JSON.stringify(slice.call(arguments)));
}
_.delay(myFunc, 500, 1, 2, 3, 4)
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}