好的,让我们通过替换来解决这个问题。我们开始:
Function.prototype.call.apply(Array.prototype.slice, arguments);
我们所知道的:
-
Function.prototype.call 是一个函数。
-
call 的this 指针指向Function.prototype。
- 我们使用
apply将call的this指针改为Array.prototype.slice。
-
arguments 被应用(不作为参数传递)到call。
因此上面的语句等价于:
Array.prototype.slice.call(arguments[0], arguments[1], ...);
由此我们看到:
-
Array.prototype.slice 是一个函数。
-
slice 的this 指针指向Array.prototype。
- 我们使用
call将slice的this指针改为arguments[0]。
-
arguments[1], ... 作为参数传递给slice。
这与:
arguments[0].slice(arguments[1], ...);
这样做的好处是我们在一行中为slice 创建了一个fast unbound wrapper。
编辑:创建快速未绑定包装器的更好方法如下(请注意,它可能不适用于某些较旧的浏览器,但您现在不必担心 - 您可以对于不支持bind的浏览器,请始终使用shim):
var slice = Function.prototype.call.bind(Array.prototype.slice);
这与:
function slice() {
return Function.prototype.call.apply(Array.prototype.slice, arguments);
}
它是如何工作的:
-
Function.prototype.call 是一个函数。
-
call 的this 指针指向Function.prototype。
- 我们使用
bind将call的this指针改为Array.prototype.slice。
-
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);
- 使用它,您可以使用
call 或apply 轻松创建未绑定的包装器。
- 您可以使用
classOf 来获取值的内部[[Class]]。
- 您可以在 for in 循环中使用
ownPropertyOf。
- 您可以使用
concatenate 来加入数组。
- 您可以使用
arrayFrom 创建数组。