[英]JavaScript: The Good Parts - chapter 8, function.apply()
对于以下基于“ JavaScript:优质零件”的第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旨在提取value属性的值 。 然后,我们绑定一个具有值属性名称/值对的对象,并执行x函数。 x函数进入所提供的对象,就像该对象的方法一样,并返回value属性的值 。
我不了解这是如何实现的(我注意到Crockford准使用666 )。 提前致谢。
apply的第二个参数必须是一个数组,如果[2]改为2,则会发生这种情况
Array.prototype.slice.apply(arguments,2); 未捕获的TypeError:Function.prototype.apply:参数列表具有错误的类型
arguments
是一个烘培的属性,它代表发送给类似对象数组中的函数的所有参数。 切片此数组将删除不需要的部分。 在bind的情况下,将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
被传递并没有被用作用于该方法的自变量)。
Function.prototype.apply()
需要两个参数,对于一个值this
和的阵列 arguments
。 即使只有一个参数,它也需要一个数组。
所以:
slice.apply(arguments, [1]);
几乎等同于:
arguments.slice(1);
我说这几乎是因为arguments
不是真正的数组,并且它没有切片方法,这就是为什么您必须采用时髦的方式。
正如其他人在评论中指出的那样,您可以改用call
来使其更整洁。 call
预计,该值this
,然后任意数量的附加参数的方式。 这意味着您可以改为:
slice.call(arguments, 1);
假设您有一些函数,不管它做什么,都将其绑定到上下文并传递一些参数。
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
切片,以包含所有传入的参数。
仔细看看Function.prototype.apply() , arguments对象和slice函数 。
apply
将对象作为调用函数的上下文,并将参数数组的附加可选参数发送给被调用的函数。
slice(0)
通常用于将类似数组的对象转换为数组。
slice.apply(arguments, [0])
几乎等同于arguments.slice(0),不同之处在于它将不会更改发送到主函数的参数,但会导致一个新数组,保证是一个数组。
与上面类似,但是将从数组中删除第一个条目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.