简体   繁体   English

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

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

For the following code, based on page 84 of "JavaScript: The Good Parts", can someone explain why [1] and [0] are used? 对于以下基于“ JavaScript:优质零件”的第84页的代码,有人可以解释为什么使用[1][0]吗? I understand that they're supplying the arguments 1 and 0 to slice, respectively, but what's the point of that? 我知道他们分别提供参数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.

I believe I understand the big picture - the function x has been designed to extract the value of the value property. 我相信我了解全局-函数x旨在提取value属性的 We then bind an object that has a value property name/value pair and execute the x function. 然后,我们绑定一个具有属性名称/值对的对象,并执行x函数。 The x function reaches into the supplied object, as if it where a method of that object, and returns the value of the value property. x函数进入所提供的对象,就像该对象的方法一样,并返回value属性的

What I do not understand is how this is accomplished (I note Crockford's quasi-amusing use of 666 ). 我不了解这是如何实现的(我注意到Crockford准使用666 )。 Thanks in advance. 提前致谢。

The second argument for apply needs to be an array, if [2] were 2 instead, this would happen apply的第二个参数必须是一个数组,如果[2]改为2,则会发生这种情况

Array.prototype.slice.apply(arguments, 2); Array.prototype.slice.apply(arguments,2); Uncaught TypeError: Function.prototype.apply: Arguments list has wrong type 未捕获的TypeError:Function.prototype.apply:参数列表具有错误的类型

arguments is a baked in property which represents all of the arguments send to a function in an array like object. arguments是一个烘培的属性,它代表发送给类似对象数组中的函数的所有参数。 slicing this array will remove unwanted parts. 切片此数组将删除不需要的部分。 In the case of bind, that is passed as an argument so slicing after 1 will remove that. 在bind的情况下,将that作为参数传递,因此在1之后进行切片将删除该参数。

As a result 结果是

var args = slice.apply(arguments, [1]); // Why is [1] here?

Will take all of the extra arguments sent to bind, for example .bind({},1,2,3,4) will result in args being [1,2,3,4] 将采用所有发送来绑定的额外参数,例如.bind({},1,2,3,4)将导致args为[1,2,3,4]

Next, a function is returned 接下来,返回一个函数

return function () { 
 return method.apply(that, args.concat(slice.apply(arguments, [0]))); // Why is [0] here?
};

that is going to be the new scope to use, method is the function that bind was originally called from, args.concat is going to take the previous array examined, and then add in all of the arguments which the method was called with, which is why [0] was used as opposed to [1] (where that was passed and was not being used as an argument for the method). that是要使用的新作用域, method是最初从bind调用的函数, args.concat将接受先前检查的数组,然后添加使用该方法调用的所有参数,其中就是为什么[0]被用作相对于[1]其中, that被传递并没有被用作用于该方法的自变量)。

Function.prototype.apply() takes 2 arguments, a value for this and an array of arguments . Function.prototype.apply()需要两个参数,对于一个值this和的阵列 arguments Even if there is only one argument, it expects an array. 即使只有一个参数,它也需要一个数组。

So: 所以:

slice.apply(arguments, [1]);

is almost equivalent to: 几乎等同于:

arguments.slice(1);

I say almost because arguments is not a real array, and it does not have a slice method, which is why you have to do this the funky way. 我说这几乎是因为arguments不是真正的数组,并且它没有切片方法,这就是为什么您必须采用时髦的方式。

As others note in the comments, you can use call instead to make this cleaner. 正如其他人在评论中指出的那样,您可以改用call来使其更整洁。 call expects a value for this this and then any number of additional individual arguments. call预计,该值this ,然后任意数量的附加参数的方式。 Which means you can instead do: 这意味着您可以改为:

slice.call(arguments, 1);

Let's assume you have some function, it doesn't matter what it does, and you are binding it to a context and passing some arguments in. 假设您有一些函数,不管它做什么,都将其绑定到上下文并传递一些参数。

function myFunc(a, b, c) {

}.bind(myContext, arg1, arg2)

Now let's look at what .bind does: 现在让我们看一下.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 takes the arguments context, [arg1, arg2, ...] . apply接受参数context, [arg1, arg2, ...] So slice.apply(arguments, [1]) is like calling arguments.slice(1) . 所以slice.apply(arguments, [1])就像调用arguments.slice(1) (As noted in the comments, you could use call and drop the array brackets.) The purpose of the 1 is to start the slice from the 1 index. (如注释中所述,您可以使用call并放下数组括号。) 1的目的是从1索引开始切片。 that which is passed in is arguments[0] . that这是在传递是arguments[0] Any arguments passed to .bind after the context would be included in this slice. 上下文之后传递给.bind任何参数都将包含在此片中。 So you might call myFunc.bind(myContext, arg1, arg2) ; 因此,您可以调用myFunc.bind(myContext, arg1, arg2) that slice would set args to [arg1, arg2] . 该分slice会将args设置为[arg1, arg2]

  return function () { 
    return method.apply(that, args.concat(slice.apply(arguments, [0]))); // Why is [0] here?
  };
};

This is the function that gets returned by .bind ; 这是.bind返回的函数; this is the function that will actually be called when myFunc(some, params, here) is called directly. 这是当直接调用myFunc(some, params, here)时实际上将被调用的函数。 The slice in this case is the entire arguments list; 在这种情况下, slice是整个参数列表; slicing from 0 returns the whole list, converted to an array, so that it can be passed to the outer apply. 从0切片将返回整个列表,并将其转换为数组,以便可以将其传递到外部apply.


TL;DR TL; DR

The first arguments are sliced from 1 to drop that and get all the arguments after it. 第一个参数从薄片1下降that和之后获得的所有参数。 The second list is sliced from 0 to include ALL the arguments passed in. 第二个列表从0切片,以包含所有传入的参数。

Documentation and Context 文档和上下文

Take a closer look at Function.prototype.apply() , the arguments object , and the slice function . 仔细看看Function.prototype.apply()arguments对象slice函数

apply takes an object as the context to call a function, with an additional optional parameter of an array of arguments to send to the called function. apply将对象作为调用函数的上下文,并将参数数组的附加可选参数发送给被调用的函数。

Slice(0) 片(0)

slice(0) is often used to covert array-like objects into arrays. slice(0)通常用于将类似数组的对象转换为数组。

slice.apply(arguments, [0]) is nearly equivalent to arguments.slice(0), except that it will not alter the arguments sent to the main function, but will result in a new array, guaranteed to be an array. slice.apply(arguments, [0])几乎等同于arguments.slice(0),不同之处在于它将不会更改发送到主函数的参数,但会导致一个新数组,保证是一个数组。

Slice(1) 片(1)

Similar to above, but will remove the first entry from the array. 与上面类似,但是将从数组中删除第一个条目。

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

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