对于以下代码,基于“JavaScript:The Good Parts”的第84页,有人可以解释为什么使用 [1] 和 [0] ?我知道他们分别为切片提供 1 和 0 这些参数,但这有什么意义呢?
Function.prototype.bind = function (that) {
var method = this;
var slice = Array.prototype.slice;
var args = slice.apply(arguments, [1]); // Why is [1] here?
return function () {
return method.apply(that, args.concat(slice.apply(arguments, [0]))); // Why is [0] here?
};
};
var x = function () {
return this.value;
}.bind({ value: 666 });
console.log(x()); // Returns 666.
我相信我理解大局 - 函数 x 旨在提取值属性的值。然后,我们绑定一个具有值属性名称/值对的对象,并执行 x 函数。 x 函数到达提供的对象,就好像它是该对象的方法一样,并返回值属性的值。
我不明白这是如何实现的(我注意到Crockford对 666 的准有趣使用)。提前谢谢。
答案 0 :(得分:3)
apply的第二个参数需要是一个数组,如果[2]为2,则会发生这种情况
Array.prototype.slice.apply(arguments,2); 未捕获的TypeError:Function.prototype.apply:参数列表的类型错误
arguments
是一个烘焙的属性,它表示发送给像object这样的数组中的函数的所有参数。切片此数组将删除不需要的部分。在绑定的情况下,that
作为参数传递,因此在1之后切片将删除它。
结果
var args = slice.apply(arguments, [1]); // Why is [1] here?
将所有发送的额外参数绑定到绑定,例如.bind({},1,2,3,4)将导致args为[1,2,3,4]
接下来,返回一个函数
return function () {
return method.apply(that, args.concat(slice.apply(arguments, [0]))); // Why is [0] here?
};
that
将成为新的使用范围,method
是最初调用bind的函数,args.concat
将检查先前的数组,然后添加在调用该方法的所有参数中,这就是为什么使用[0]
而不是[1]
(其中that
被传递并且未被用作方法的参数的原因)。
答案 1 :(得分:0)
Function.prototype.apply()
需要2个参数,this
的值和arguments
的数组。即使只有一个参数,它也需要一个数组。
所以:
slice.apply(arguments, [1]);
几乎相当于:
arguments.slice(1);
我说几乎是因为arguments
不是真正的数组,并且它没有切片方法,这就是为什么你必须以时髦的方式做到这一点。
正如其他人在评论中指出的那样,您可以使用call
来改善它。 call
期望此this
的值,然后是任意数量的其他单个参数。这意味着您可以改为:
slice.call(arguments, 1);
答案 2 :(得分:0)
让我们假设你有一些功能,它的作用并不重要,你将它绑定到一个上下文并传递一些参数。
function myFunc(a, b, c) {
}.bind(myContext, arg1, arg2)
现在让我们看看.bind
做了什么:
Function.prototype.bind = function (that) {
var method = this;
var slice = Array.prototype.slice;
var args = slice.apply(arguments, [1]); // Why is [1] here?
apply
接受参数context, [arg1, arg2, ...]
。因此slice.apply(arguments, [1])
就像调用arguments.slice(1)
一样。 (如评论中所述,您可以使用call
并删除数组括号。)1
的目的是从1
索引开始切片。传入的that
是arguments[0]
。在上下文之后传递给.bind
的任何参数都将包含在此切片中。所以你可以打电话给myFunc.bind(myContext, arg1, arg2)
; slice
会将args
设置为[arg1, arg2]
。
return function () {
return method.apply(that, args.concat(slice.apply(arguments, [0]))); // Why is [0] here?
};
};
这是由.bind
返回的函数;这是直接调用myFunc(some, params, here)
时实际调用的函数。在这种情况下,slice
是整个参数列表;从0切片返回整个列表,转换为数组,以便它可以传递到外部apply.
第一个参数从1
切换到删除that
并获取其后的所有参数。第二个列表从0
切片,包括传入的所有参数。
答案 3 :(得分:0)
仔细查看Function.prototype.apply(),arguments object和slice function。
apply
将一个对象作为调用函数的上下文,并使用一个参数数组的附加可选参数发送给被调用函数。
slice(0)
通常用于将类似数组的对象转换为数组。
slice.apply(arguments, [0])
几乎等于arguments.slice(0),除了它不会改变发送到main函数的参数,但会产生一个新的数组,保证是一个数组。
与上面类似,但会删除数组中的第一个条目。