简体   繁体   English

JavaScript call()和Prototype - Slice Function

[英]JavaScript call() and Prototype - Slice Function

I'm reading the MDN Article on slice in JavaScript. 我正在阅读关于JavaScript的sliceMDN文章 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. sliceArray.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创建返回结果的新函数callthis对象设置为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 ,要绑定slicethiscall ,以实现相同的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM