3

可能重复:
chain call 和 apply 在一起是什么意思?

我发现了一些这样的代码:

function fun() {
    return Function.prototype.call.apply(Array.prototype.slice, arguments);
}

我知道 js 中的calland apply,但是当他们走到一起时我很困惑。

然后我想知道如果

Function.prototype.call.apply(Array.prototype.slice, arguments)

是相同的 :

Array.prototype.slice.apply(arguments);

如果没有,第一行是做什么的?

4

2 回答 2

11

好吧,让我们通过替换来解决这个问题。我们从:

Function.prototype.call.apply(Array.prototype.slice, arguments);

我们所知道的:

  1. Function.prototype.call是一个函数。
  2. 指向的this指针。callFunction.prototype
  3. 我们apply用来改变 to的this指针。callArray.prototype.slice
  4. arguments应用于(不作为参数传递)到call.

因此上面的语句等价于:

Array.prototype.slice.call(arguments[0], arguments[1], ...);

由此我们看到:

  1. Array.prototype.slice是一个函数。
  2. 指向的this指针。sliceArray.prototype
  3. 我们call用来改变 to的this指针。slicearguments[0]
  4. arguments[1], ...作为参数传递给slice.

这与以下内容相同:

arguments[0].slice(arguments[1], ...);

这样做的好处是我们在一行中创建了一个快速的未绑定包装器slice

编辑:创建快速未绑定包装器的更好方法如下(请注意,它可能在某些较旧的浏览器中不起作用,但您现在不必担心 - 您可能总是对不支持的浏览器使用shim支持bind):

var slice = Function.prototype.call.bind(Array.prototype.slice);

这与以下内容相同:

function slice() {
    return Function.prototype.call.apply(Array.prototype.slice, arguments);
}

这个怎么运作:

  1. Function.prototype.call是一个函数。
  2. 指向的this指针。callFunction.prototype
  3. 我们bind用来改变 to的this指针。callArray.prototype.slice
  4. bind返回一个应用于arguments函数。call

奖励:如果您的编程风格像我的那样功能强大,那么您会发现这段代码非常有用:

var funct = Function.prototype;
var obj = Object.prototype;
var arr = Array.prototype;

var bind = funct.bind;

var unbind = bind.bind(bind);
var call = unbind(funct.call);
var apply = unbind(funct.apply);

var classOf = call(obj.toString);
var ownPropertyOf = call(obj.hasOwnProperty);
var concatenate = call(arr.concat);
var arrayFrom = call(arr.slice);
  1. 使用它,您可以使用call或轻松创建未绑定的包装器apply
  2. 您可以使用classOf来获取[[Class]]值的内部。
  3. 您可以使用ownPropertyOfinside for in 循环。
  4. 您可以使用concatenate加入阵列。
  5. 您可以arrayFrom用来创建数组。
于 2012-10-22T03:01:36.417 回答
1

使用以下行,.apply调用.call方法,调用上下文.call.slice方法,并且arguments集合作为单独的参数传递。

Function.prototype.call.apply(Array.prototype.slice, arguments);

这有效地给了我们这个:

Array.prototype.slice.call(arguments[0], arguments[1], arguments[2] /*, etc */);

这意味着.slice()将使用arguments对象中的第一项作为调用上下文来调用,其余参数作为普通参数。

因此,如果 的内容arguments是这样的:

myarray, 0, 5

你实际上是这样结束的:

myarray.slice(0, 5)

这基本上是一种不必这样做的方法:

var arr = arguments[0];
var rest = Array.prototype.slice(arguments, 1);

var result = arr.slice.apply(arr, rest);
于 2012-10-22T02:45:09.320 回答