它允许您在没有绑定到原始对象的情况下,将绑定函数作为构造函数调用。换句话说,如果您使用new
调用“绑定”函数,则它仍将像原始未绑定版本一样正常工作。
以下是一个示例:
var obj = {};
function foo(x) {
this.answer = x;
}
var bar = foo.bind(obj);
bar(42);
console.log(obj.answer);
var other = new bar(1);
console.log(obj.answer);
console.log(other.answer);
工作原理
为了简化说明,这里是一个简化版的代码,只绑定this
,不处理参数或缺少obj参数的情况:
Function.prototype.bind = function( obj ) {
var self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : obj, arguments );
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
Function.prototype.bind
返回的函数在作为函数或构造函数使用时具有不同的行为(请参见 ECMAScript 5 语言规范的
第15.3.4.5.1节和
第15.3.4.5.2节)。主要区别在于当作为构造函数调用时忽略“绑定的this”参数(因为在构造函数内部,
this
必须是新创建的对象)。因此,
bound
函数需要一种方法来确定它被如何调用。例如,
bound(123)
vs.
new bound(123)
并相应地设置
this
。
这就是 nop
函数的作用。它实质上充当一个中间的“类”,使得 bound
继承 nop
,nop
再继承 self
(即调用了 bind()
的函数)。该过程在这里设置:
nop.prototype = self.prototype
bound.prototype = new nop()
当你调用绑定的函数时,它会返回这个表达式:
self.apply( this instanceof nop ? this : obj, arguments ) )
this instanceof nop
的工作原理是通过遵循原型链来确定this
的任何原型是否等于nop.prototype
。通过设置nop.prototype = self.prototype
和bound.prototype = new nop()
,使用new bound()
创建的任何对象都将通过bound.prototype
从self
继承原始原型。因此,在函数调用内部,this instanceof nop
(即Object.getPrototypeOf(nop) == nop.prototype)为true
,并且self
使用this
(新创建的对象)进行调用。
在普通函数调用中,'bound()'(没有new
)时,this instanceof nop
将为false,因此obj
将作为this
上下文传递,这是绑定函数所期望的。
使用中间函数的原因是避免调用原始函数(在bound.prototype = new nop();
行中),原始函数可能具有副作用。