[英]JavaScript call() and Prototype - Slice Function
I'm reading the MDN Article on slice
in JavaScript. 我正在阅读关于JavaScript的
slice
的MDN文章 。 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: 它说我们可以通过将
slice
作为我们自己的函数来简化第一个例子:
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. 我不明白的是,在第二行
prototype
之后,如何才能call
。
I usually see it in the form of Array.prototype.slice.call(arguments)
or something of that sort. 我通常以
Array.prototype.slice.call(arguments)
或类似的形式看到它。
I don't understand the flow of the first two lines and how they generate this working slice
function. 我不明白前两行的流程以及它们如何生成这个工作
slice
函数。
The MDN article for Function.prototype.call()
helped me wrap my head around this. Function.prototype.call()
的MDN文章帮助我解决了这个问题。
The most simplistic way I can answer: 我能回答的最简单的方式:
In javascript, a Function has a method called
call
.在javascript中,Function有一个名为
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. 因此,您的
Array.prototype.slice.call(arguments)
示例显示您在切片函数上调用call方法。
The second line in the code that you are confused about: var slice = Function.prototype.call.bind(unboundSlice);
您感到困惑的代码中的第二行:
var slice = Function.prototype.call.bind(unboundSlice);
shows the call method belonging to the Function prototype. 显示属于Function原型的call方法。
Checkout JavaScript Prototypes if you are still confused. 如果您仍然感到困惑,请检查JavaScript原型 。
1 Functions are objects. 1功能是对象。
2 "Every JavaScript object has a prototype." 2“每个JavaScript对象都有一个原型。”
3 "The prototype is also an object." 3“原型也是一个对象。”
4 "All JavaScript objects inherit their properties and methods from their prototype." 4“所有JavaScript对象都从其原型继承其属性和方法。”
In other words, back to the most simplistic way to answer this: In javascript, a Function has a method called call
. 换句话说,回到最简单的方式来回答这个问题:在javascript中,一个Function有一个叫做
call
的方法。
As for understanding what bind
does, the that = this
vs .bind
example in this article helps make sense of what is going on. 至于理解
bind
作用,本文中的this that = this
vs .bind
示例有助于理解正在发生的事情。
If that was confusing, then make sure you understand context and scope 如果这令人困惑,那么请确保您了解上下文和范围
tl;dr: TL;博士:
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. .slice
是一种提取数组子集的数组方法。 It operates on the value of this
. 它运行在价值
this
。 .call
is a method every function has, it lets you set the this
value for a function execution. .call
是每个函数都有的方法,它允许你为函数执行设置this
值。 So, the above line lets us execute slice
as a method of arguments
, without having to mutate arguments
itself. 因此,上面的行让我们执行
slice
作为arguments
的方法,而不必自己改变arguments
。 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. 如上所述,
.call
是每个函数都有的方法。 It also operates on this
, which is expected to be a function. 此外,她也
this
,它有望成为一个功能。 It calls this
and sets the this
value of that function to the first argument. 它调用
this
并将该函数的this
值设置为第一个参数。 You could think of call
as being similar to 你可以认为
call
类似于
function call(thisValue, arg1, arg2, ...) {
return this.apply(thisValue, [arg1, arg2, ...]);
}
Note how it calls this
as a function. 注意它是如何调用
this
作为一个功能。
.bind
is also a method every function has. .bind
也是每个函数都有的方法。 It returns a new function which has its this
value fixed to the first argument you pass in. 它返回它有其新的功能
this
固定你传递的第一个参数值。
Let's consider what the resulting function of call.bind(unboundSlice)
would look like: 让我们考虑一下
call.bind(unboundSlice)
的结果函数是什么样的:
function boundCall(thisValue, arg1, arg2, ...) {
return unboundSlice.apply(thisValue, [arg1, arg2, ...]);
}
We simply replaced this
with unboundSlice
. 我们只是用
unboundSlice
替换this
。 boundCall
will now always call unboundSlice
. boundCall
现在将始终调用unboundSlice
。
slice
is a property of Array.prototype
, and it expects its this
object to be Array-like. slice
是Array.prototype
一个属性,它期望它的this
对象是类似于Array的。 You can use it on Array-like objects (that have a length property and have properties that you can index) that don't have their own slice function like so: 您可以在类似于Array的对象(具有length属性并具有可以索引的属性)上使用它,它们没有自己的切片函数,如下所示:
Array.prototype.slice.call(arraylikething);
That's a lot of typing, so we can make a function to do the same thing: 这是很多打字,所以我们可以做一个功能来做同样的事情:
var slice = function(arraylikething){
return Array.prototype.slice.call(arraylikething);
};
JavaScript provides Function.prototype.bind
to bind functions to a specified this
object. JavaScript提供了
Function.prototype.bind
来将函数绑定到指定的this
对象。 So we can accomplish the same thing a bit more easily: 所以我们可以更轻松地完成同样的事情:
var slice = Function.prototype.call.bind(Array.prototype.slice);
bind
creates a new function that returns the result of call
with its this
object set to Array.prototype.slice
, the same as what we did manually above, and equivalent to your code. bind
创建返回结果的新函数call
其this
对象设置为Array.prototype.slice
,同我们上面手工做了,相当于你的代码。
The answer from Chris Dillinger is correct and informative. Chris Dillinger的答案是正确和有益的。 But here's another way to think about it.
但这是考虑它的另一种方式。 You're being asked, in essence, to define
从本质上讲,你被要求定义
Function.prototype.call.bind(Array.prototype.slice)
Which you can look at this way: 您可以这样看待:
fn.bind(context)
==> function(...args) {return context.fn(...args);}
// 1. definition of `bind` (oversimplified, but enough for this case)
fn.bind(unboundSlice)
==> function(...args) {return unboundSlice.fn(...args);}
// 2. substitute `unboundSlice` for `context`
Function.prototype.call.bind(unboundSlice)
==> function(...args) {return unboundSlice[Function.prototype.call](...args);}
// 3. substitute `Function.prototype.call` for `fn`.
Function.prototype.call.bind(unboundSlice)
==> function(...args) {return unboundSlice[.call(...args);}
// 4. walk the prototype chain
Function.prototype.call.bind(Array.prototype.slice)
==> function(...args) {return Array.prototype.slice.call(...args);}
// 5. substitue `Array.prototype.slice` for `unboundSlice`
The only step that's even slightly tricky is step 4, where you have to realize that all functions inherit the call
method from their prototype chain, so invoking call
on them is merely an alternative means of invoking the functions themselves. 即使有点棘手的唯一步骤是第4步,在那里你必须认识到,所有的功能继承
call
从他们的原型链的方法,所以调用call
它们只是调用函数本身的替代手段。
In the first line, Array.prototype.slice
(which is a method) is simply referenced via unboundSlice
. 在第一行中,
Array.prototype.slice
(这是一个方法)只是通过unboundSlice
引用。 You're essentially 'extracting' the slice method from Array.prototype
. 你实际上是从
Array.prototype
'提取'切片方法。
In the second line, the same thing happens for Function.prototype.call
, which is also a method of ALL functions. 在第二行中,
Function.prototype.call
也发生了同样的事情,它也是ALL函数的一种方法。 (it's defined in Function.prototype
, and inherited by all functions). (它在
Function.prototype
定义,并由所有函数继承)。
Next, by using .bind(unboundSlice)
the Call function's this
value is bound to the reference to Array.prototype.slice
, which essentially results in the same thing as Array.prototype.slice.call()
, where call also has its this
bound to slice
, because of it being a method of it, AND because it's being called like that. 接下来,通过使用
.bind(unboundSlice)
呼叫功能的this
值被绑定到参考Array.prototype.slice
,基本上导致同样的事情Array.prototype.slice.call()
在通话也有this
绑定到slice
,因为它是它的一种方法,因为它被这样调用。
Lastly, the bound call method is referenced via var slice
; 最后,通过
var slice
引用绑定调用方法;
The general idea here is that you're able to use the functionality of an array method (slice) in another context (the global scope). 这里的一般想法是,您可以在另一个上下文(全局范围)中使用数组方法(切片)的功能。
So now, instead of calling call
when it was already a method of slice
, you're binding slice
to be the this
value of call
in order to achieve the same behaviour. 所以,现在,而不是调用
call
时,它已经是一个方法slice
,要绑定slice
是this
值call
,以实现相同的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.