JavaScript call() 和原型 - 切片函数
JavaScript call() and Prototype - Slice Function
我正在 JavaScript 阅读 slice
上的 MDN Article。除了标题为 Array-Like Objects.
的部分中的第二个示例外,我了解所有内容
它说我们可以通过使 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]
我不明白的是 call
怎么会在第二行的 prototype
之后。
我通常以 Array.prototype.slice.call(arguments)
或类似的形式看到它。
我不明白前两行的流程以及它们如何生成这个有效的 slice
函数。
Function.prototype.call()
的 MDN article 帮助我解决了这个问题。
我能回答的最简单的方式:
In javascript, a Function has a method called call
. A function is an
object, and all objects inherit methods and properties from their
prototype.
所以你的例子 Array.prototype.slice.call(arguments)
显示你在切片函数上调用 call 方法。
你疑惑的代码中第二行:var slice = Function.prototype.call.bind(unboundSlice);
显示属于Function原型的call方法
如果您仍然感到困惑,请查看 JavaScript Prototypes。
1 函数是对象。
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."
换句话说,回到最简单的方式来回答这个问题:在javascript中,一个Function有一个方法叫做call
.
至于理解 bind
的作用,this 文章中的 that = this
与 .bind
示例有助于理解正在发生的事情。
如果这让您感到困惑,请确保您理解 context and scope
slice
是 Array.prototype
的 属性,并且它期望其 this
对象是 Array-like。您可以在没有自己的切片函数的类数组对象(具有长度 属性 并具有可以索引的属性)上使用它,如下所示:
Array.prototype.slice.call(arraylikething);
需要大量输入,所以我们可以创建一个函数来完成同样的事情:
var slice = function(arraylikething){
return Array.prototype.slice.call(arraylikething);
};
JavaScript 提供 Function.prototype.bind
将函数绑定到指定的 this
对象。所以我们可以更容易地完成同样的事情:
var slice = Function.prototype.call.bind(Array.prototype.slice);
bind
创建一个新函数 returns call
的结果,其 this
对象设置为 Array.prototype.slice
,与我们所做的相同手动在上面,相当于你的代码。
在第一行中,Array.prototype.slice
(这是一个方法)只是通过unboundSlice
引用。您本质上是 'extracting' 来自 Array.prototype
.
的 slice 方法
第二行,Function.prototype.call
也是一样,也是ALL函数的一个方法。 (它在 Function.prototype
中定义,并被所有函数继承)。
接下来,通过使用 .bind(unboundSlice)
,Call 函数的 this
值被绑定到对 Array.prototype.slice
的引用,这基本上导致与 Array.prototype.slice.call()
相同的结果,其中call 也有它的 this
绑定到 slice
,因为它是它的一个方法,而且因为它被这样调用。
最后,通过var slice
;
引用了绑定的调用方法
这里的总体思路是您可以在另一个上下文(全局范围)中使用数组方法(切片)的功能。
所以现在,当 call
已经是 slice
的方法时,您不再调用 call
,而是将 slice
绑定为 this
的值 call
以实现相同的行为。
Chris Dillinger 的回答正确且内容丰富。但这是另一种思考方式。本质上,你被要求定义
Function.prototype.call.bind(Array.prototype.slice)
哪个可以这样看:
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`
唯一有点棘手的步骤是第 4 步,您必须意识到所有函数都从其原型链继承 call
方法,因此对它们调用 call
只是一种替代方法调用函数本身的方法。
tl;博士:
var slice = Function.prototype.call.bind(unboundSlice);
是简写法:
var slice = function(value, start, end) {
return unboundSlice.call(value, start, end);
};
我们再考虑一下这一行:
Array.prototype.slice.call(arguments)
.slice
是数组方法,提取数组的子集。它对 this
的值进行操作。 .call
是每个函数都有的方法,它可以让您设置函数执行的 this
值。因此,上面这行代码让我们将 slice
作为 arguments
的方法来执行,而不必改变 arguments
本身。我们可以做到
arguments.slice = Array.prototype.slice;
arguments.slice();
但这并不干净。
现在正在看
Function.prototype.call.bind(unboundSlice);
如前所述,.call
是 每个 函数都有的方法。它还对 this
进行操作,这应该是一个函数。它调用 this
并将该函数的 this
值设置为第一个参数。您可以认为 call
类似于
function call(thisValue, arg1, arg2, ...) {
return this.apply(thisValue, [arg1, arg2, ...]);
}
注意它如何将 this
作为函数调用。
.bind
也是每个函数都有的方法。它 returns 一个新函数,其 this
值固定为您传入的第一个参数。
让我们考虑一下 call.bind(unboundSlice)
的结果函数是什么样的:
function boundCall(thisValue, arg1, arg2, ...) {
return unboundSlice.apply(thisValue, [arg1, arg2, ...]);
}
我们只是用unboundSlice
替换了this
。 boundCall
现在总是调用 unboundSlice
.
我正在 JavaScript 阅读 slice
上的 MDN Article。除了标题为 Array-Like Objects.
它说我们可以通过使 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]
我不明白的是 call
怎么会在第二行的 prototype
之后。
我通常以 Array.prototype.slice.call(arguments)
或类似的形式看到它。
我不明白前两行的流程以及它们如何生成这个有效的 slice
函数。
Function.prototype.call()
的 MDN article 帮助我解决了这个问题。
我能回答的最简单的方式:
In javascript, a Function has a method called
call
. A function is an object, and all objects inherit methods and properties from their prototype.
所以你的例子 Array.prototype.slice.call(arguments)
显示你在切片函数上调用 call 方法。
你疑惑的代码中第二行:var slice = Function.prototype.call.bind(unboundSlice);
显示属于Function原型的call方法
如果您仍然感到困惑,请查看 JavaScript Prototypes。
1 函数是对象。
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."
换句话说,回到最简单的方式来回答这个问题:在javascript中,一个Function有一个方法叫做call
.
至于理解 bind
的作用,this 文章中的 that = this
与 .bind
示例有助于理解正在发生的事情。
如果这让您感到困惑,请确保您理解 context and scope
slice
是 Array.prototype
的 属性,并且它期望其 this
对象是 Array-like。您可以在没有自己的切片函数的类数组对象(具有长度 属性 并具有可以索引的属性)上使用它,如下所示:
Array.prototype.slice.call(arraylikething);
需要大量输入,所以我们可以创建一个函数来完成同样的事情:
var slice = function(arraylikething){
return Array.prototype.slice.call(arraylikething);
};
JavaScript 提供 Function.prototype.bind
将函数绑定到指定的 this
对象。所以我们可以更容易地完成同样的事情:
var slice = Function.prototype.call.bind(Array.prototype.slice);
bind
创建一个新函数 returns call
的结果,其 this
对象设置为 Array.prototype.slice
,与我们所做的相同手动在上面,相当于你的代码。
在第一行中,Array.prototype.slice
(这是一个方法)只是通过unboundSlice
引用。您本质上是 'extracting' 来自 Array.prototype
.
第二行,Function.prototype.call
也是一样,也是ALL函数的一个方法。 (它在 Function.prototype
中定义,并被所有函数继承)。
接下来,通过使用 .bind(unboundSlice)
,Call 函数的 this
值被绑定到对 Array.prototype.slice
的引用,这基本上导致与 Array.prototype.slice.call()
相同的结果,其中call 也有它的 this
绑定到 slice
,因为它是它的一个方法,而且因为它被这样调用。
最后,通过var slice
;
这里的总体思路是您可以在另一个上下文(全局范围)中使用数组方法(切片)的功能。
所以现在,当 call
已经是 slice
的方法时,您不再调用 call
,而是将 slice
绑定为 this
的值 call
以实现相同的行为。
Chris Dillinger 的回答正确且内容丰富。但这是另一种思考方式。本质上,你被要求定义
Function.prototype.call.bind(Array.prototype.slice)
哪个可以这样看:
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`
唯一有点棘手的步骤是第 4 步,您必须意识到所有函数都从其原型链继承 call
方法,因此对它们调用 call
只是一种替代方法调用函数本身的方法。
tl;博士:
var slice = Function.prototype.call.bind(unboundSlice);
是简写法:
var slice = function(value, start, end) {
return unboundSlice.call(value, start, end);
};
我们再考虑一下这一行:
Array.prototype.slice.call(arguments)
.slice
是数组方法,提取数组的子集。它对 this
的值进行操作。 .call
是每个函数都有的方法,它可以让您设置函数执行的 this
值。因此,上面这行代码让我们将 slice
作为 arguments
的方法来执行,而不必改变 arguments
本身。我们可以做到
arguments.slice = Array.prototype.slice;
arguments.slice();
但这并不干净。
现在正在看
Function.prototype.call.bind(unboundSlice);
如前所述,.call
是 每个 函数都有的方法。它还对 this
进行操作,这应该是一个函数。它调用 this
并将该函数的 this
值设置为第一个参数。您可以认为 call
类似于
function call(thisValue, arg1, arg2, ...) {
return this.apply(thisValue, [arg1, arg2, ...]);
}
注意它如何将 this
作为函数调用。
.bind
也是每个函数都有的方法。它 returns 一个新函数,其 this
值固定为您传入的第一个参数。
让我们考虑一下 call.bind(unboundSlice)
的结果函数是什么样的:
function boundCall(thisValue, arg1, arg2, ...) {
return unboundSlice.apply(thisValue, [arg1, arg2, ...]);
}
我们只是用unboundSlice
替换了this
。 boundCall
现在总是调用 unboundSlice
.