I came across the following code:
var f = function () {
var args = Array.prototype.slice.call(arguments).splice(1);
// some more code
};
Basically, the result in args
is an array that is a copy of the arguments
without its first element.
But what I can't understand exactly is why f
's arguments
(which is an object that holds the function's inputted arguments into an array-like object) object is being passed to the slice
method and how slice(1)
is removing the first element (positioned at index 0).
Can anyone please explain it for me?
P.S. The code is from this partial application function
<Note>
The actual code from that linked answer is:
i.e. "slice", not "splice"
</Note>
First of all, the
slice
method is often used to make a copy of the array it's called on:So the short answer is that the code is basically emulating:
However you can't do that directly. The special
arguments
object (available inside the execution context of all JavaScript functions), although Array-like in that it supports indexing via the[]
operator with numeric keys, is not actually an Array; You can't.push
onto it,.pop
off it, or.slice
it, etc.The way the code accomplishes this is by "tricking" the
slice
function (which again is not available on thearguments
object) to run in the context ofarguments
, viaFunction.prototype.call
:Array.prototype.slice.call(arguments).splice(1)
accomplishes the same thing, but makes an extraneous call tosplice(1)
, which removes elements from the array returned fromArray.prototype.slice.call(arguments)
starting at index1
and continuing to the end of the array.splice(1)
doesn't work in IE (it's technically missing a 2nd parameter telling it how many items to remove that IE and ECMAScript require).First takes a copy of
arguments
(*), then removes all but the first item from it (in a non-standard way), and assigns those items being removed toargs
.The extra array being produced, then altered and thrown away is quite redundant. It would be better to say — as the version in the answer you linked to indeed does:
Partial function application is also a feature of the
function.bind
method, being standardised by ECMAScript Fifth Edition. Until browsers have implemented it, you can pick up an a fallback JS-native version from the bottom of this answer.*:
array.slice()
is the normal idiom for copying an array, andarray.slice(1)
for taking the tail. It has it be called explicitly through theArray.prototype
becausearguments
is not an Array, even though it looks just like one, so doesn't have the normal array methods. This is another of JavaScript's weird mistakes.You quite often see people using the
Array.prototype
methods on objects that aren't Arrays; the ECMAScript Third Edition standard goes out of its way to say this is OK to do for thearguments
array-like, but not that you may also do it on other array-likes that may be host objects, such as NodeList or HTMLCollection. Although you might get away with callingArray.prototype
methods on a non-Array in many browsers today, the only place it is actually safe to do so is onarguments
.The returned value of a splice is an array of the elements that were removed, but the original array (or array-like object), is truncated at the splice index.
Making a copy with slice preserves the original arguments array, presumably for use later in the function.
In this case the same result can be had with
args = [].slice.call(arguments, 1)