繁体   English   中英

JavaScript:优良部件-第8章,function.apply()

[英]JavaScript: The Good Parts - chapter 8, function.apply()

对于以下基于“ JavaScript:优质零件”的第84页的代码,有人可以解释为什么使用[1][0]吗? 我知道他们分别提供参数10来进行切片,但是这样做有什么意义呢?

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.


TL; DR

第一个参数从薄片1下降that和之后获得的所有参数。 第二个列表从0切片,以包含所有传入的参数。

文档和上下文

仔细看看Function.prototype.apply()arguments对象slice函数

apply将对象作为调用函数的上下文,并将参数数组的附加可选参数发送给被调用的函数。

片(0)

slice(0)通常用于将类似数组的对象转换为数组。

slice.apply(arguments, [0])几乎等同于arguments.slice(0),不同之处在于它将不会更改发送到主函数的参数,但会导致一个新数组,保证是一个数组。

片(1)

与上面类似,但是将从数组中删除第一个条目。

暂无
暂无

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

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