同时使用 call 和 apply,创建一个快速的解绑定包装器?

在 Javascript秘密花园 看到这样一段:

另一个技巧是同时使用 call 和 apply,创建一个快速的解绑定包装器。

function Foo() {}

Foo.prototype.method = function(a, b, c) {
    console.log(this, a, b, c);
};

// 创建一个解绑定的 "method"
// 输入参数为: this, arg1, arg2...argN
Foo.method = function() {

    // 结果: Foo.prototype.method.call(this, arg1, arg2... argN)
    Function.call.apply(Foo.prototype.method, arguments);
};

代码中Function.call.apply该如何理解?解绑定包装器又是干嘛的?

出处:http://bonsaiden.github.io/JavaScript-Garden/zh/#other

阅读 3.4k
1 个回答

解绑定:
我们想让Foo.methodFoo.prototype.method完成一样的功能,但是想显式地指定方法体中的this对象(通过第一个参数),而不是Foo.prototype.method本身绑定的。即实现:

Foo.method = function(context, arg0, arg1...){
//注释1:内部调用Foo.prototype.method,并且以context作为其this对象,剩下的arg0等作为参数
}

Function.call.apply:
要实现上面注释1中的目的,很明显要用Foo.prototype.method的call方法改变其this对象并传进参数,即:

Foo.prototype.method.call(context, arg0, arg1, ...);

但是arg0等参数列表是不定长的。
然后我们注意到[context, arg0, arg1, ...]可以看做是Foo.method这个方法的arguments,它是一个类数组;
所以

Foo.prototype.method.call(context, arg0, arg1, ...);

可以理解为:

call方法.apply(Foo.prototype.method, arguments);

以Foo.prototype.method为作用对象调用一个call方法,以Foo.method的arguments为参数。
至于这个call方法,是Function.call、Function.prototype.call、xxxFunc.call其实都无所谓,我们只是借用,题目中用的是Function.call。也就是

Function.call.apply(Foo.prototype.method, arguments);

的由来啦。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏