当我偶然发现用于创建“快速,未绑定的包装器”的Function.call.apply hack时,我正在浏览JavaScript Garden。它说:
另一个技巧是同时使用call和apply来创建快速,未绑定的包装器。
function Foo() {} Foo.prototype.method = function(a, b, c) { console.log(this, a, b, c); }; // Create an unbound version of "method" // It takes the parameters: this, arg1, arg2...argN Foo.method = function() { // Result: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); };
我不明白的是,当Function.apply足够时,为什么还要使用Function.call.apply。毕竟,它们在语义上都是等价的。
答案 0 :(得分:14)
不,Function.call.apply
和Function.apply
在这种情况下不一样。
假设原始调用者调用
Foo.method(t, x, y, z)
通过调用和一起应用,就像在JavaScript Garden代码中一样。执行
Function.call.apply(Foo.prototype.method, arguments);
(松散地,在数组表示法中写arguments
):
Function.call.apply(Foo.prototype.method, [t, x, y, z]);
使用Function.call
调用this==Foo.prototype.method
:
Foo.prototype.method.call(t, x, y, z)
调用Foo.prototype.method
,this
设置为t
,参数x
,y
和z
。甜。就像在评论中一样。我们已成功制作了包装纸。
现在假设你左边只说Function.apply
而不是Function.call.apply
,你声称它在语义上是等价的。你会有
Function.apply(Foo.prototype.method, arguments);
(松散地)
Function.apply(Foo.prototype.method, [t, x, y, z]);
调用函数Function
(唉!),其中this
设置为Foo.prototype.method
,参数t
,x
,y
和z
。
完全不一样。
答案 1 :(得分:4)
这意味着您可以使用另一个对象中的方法。
一个很好的例子是所有函数都有的参数变量,它就像一个数组但不是一个数组,所以你可以在它上面调用数组的方法:
Array.prototype.join.call(arguments, ",");