I'm reading the MDN Article on slice
in JavaScript. I understand everything except the 2nd example in the section titled Array-Like Objects.
It says we can simplify the first example by making slice
our own function as so:
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
function list() {
return slice(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
What I don't understand is how call
can come right after prototype
on the second line.
I usually see it in the form of Array.prototype.slice.call(arguments)
or something of that sort.
I don't understand the flow of the first two lines and how they generate this working slice
function.
tl;dr:
var slice = Function.prototype.call.bind(unboundSlice);
is a short way of writing:
var slice = function(value, start, end) {
return unboundSlice.call(value, start, end);
};
Let's think about this line for second:
Array.prototype.slice.call(arguments)
.slice
is an array method to extract a subset of the array. It operates on the value of this
. .call
is a method every function has, it lets you set the this
value for a function execution. So, the above line lets us execute slice
as a method of arguments
, without having to mutate arguments
itself. We could have done
arguments.slice = Array.prototype.slice;
arguments.slice();
but that is not as clean.
Now looking at
Function.prototype.call.bind(unboundSlice);
As said, .call
is a method that every function has. It also operates on this
, which is expected to be a function. It calls this
and sets the this
value of that function to the first argument. You could think of call
as being similar to
function call(thisValue, arg1, arg2, ...) {
return this.apply(thisValue, [arg1, arg2, ...]);
}
Note how it calls this
as a function.
.bind
is also a method every function has. It returns a new function which has its this
value fixed to the first argument you pass in.
Let's consider what the resulting function of call.bind(unboundSlice)
would look like:
function boundCall(thisValue, arg1, arg2, ...) {
return unboundSlice.apply(thisValue, [arg1, arg2, ...]);
}
We simply replaced this
with unboundSlice
. boundCall
will now always call unboundSlice
.
The MDN article for Function.prototype.call()
helped me wrap my head around this.
The most simplistic way I can answer:
In javascript, a Function has a method called
call
. A function is an object, and all objects inherit methods and properties from their prototype.
So your example of Array.prototype.slice.call(arguments)
shows you calling the call method on the slice function.
The second line in the code that you are confused about: var slice = Function.prototype.call.bind(unboundSlice);
shows the call method belonging to the Function prototype.
Checkout JavaScript Prototypes if you are still confused.
1 Functions are objects.
2 "Every JavaScript object has a prototype."
3 "The prototype is also an object."
4 "All JavaScript objects inherit their properties and methods from their prototype."
In other words, back to the most simplistic way to answer this: In javascript, a Function has a method called call
.
As for understanding what bind
does, the that = this
vs .bind
example in this article helps make sense of what is going on.
If that was confusing, then make sure you understand context and scope
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With