Nodejs MDN上面的Function.prototype.bind中的这一句该怎么理解?
Nodejs MDN上面的Function.prototype.bind中的这一句该怎么理解?
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== “function”) {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError(“Function.prototype.bind - what is trying to be bound is not callable”);
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
原文在这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
12行的this instanceof fNOP && oThis中,什么情况下bind中的this才会是fNOP的instance?
看上去好像是用来区分是不是在new fBound(对oThis参数的说明:The value is ignored if the bound function is constructed using the new operator.),但是&& oThis之后逻辑又看起来很奇怪。
这里的判断该如何理解?
当然,我们来详细解析一下 this instanceof fNOP && oThis 这一行代码。这行代码用于处理 bind 函数在不同调用方式下的行为,特别是在使用 new 关键字时。
解析
-
this instanceof fNOP:这部分检查当前调用fBound的上下文是否为fNOP的实例。fNOP是一个空构造函数,其原型被设置为this.prototype,即原函数的原型。如果fBound被用作构造函数(即使用new关键字),那么它的this将指向一个新创建的对象,并且这个对象的原型链会继承自fNOP。 -
&& oThis:这部分确保只有当fBound作为构造函数使用时,oThis参数才有效。如果fBound不是作为构造函数使用,则oThis会被忽略。
示例代码
让我们通过一个例子来更好地理解这一点:
function greet(name) {
console.log(`Hello, ${name}`);
}
// 使用 bind 绑定 this 到一个特定对象
const boundGreet = greet.bind({ name: 'Alice' });
// 正常调用
boundGreet(); // 输出: Hello, Alice
// 使用 new 创建一个新的对象
const BoundGreetConstructor = greet.bind({ name: 'Bob' });
const instance = new BoundGreetConstructor('Charlie');
console.log(instance.name); // 输出: Bob
详细解释
-
在第一种情况中,
boundGreet是通过.bind方法绑定到{ name: 'Alice' }的,因此调用boundGreet()时,this指向{ name: 'Alice' }。 -
在第二种情况中,我们创建了一个新的构造函数
BoundGreetConstructor,它使用.bind方法绑定到{ name: 'Bob' }。当我们使用new BoundGreetConstructor('Charlie')来创建一个新实例时,this会指向这个新创建的对象。此时,this instanceof fNOP为true,因为fNOP的原型被设置为greet.prototype。因此,fBound返回的新对象会继承fNOP的原型,而oThis参数则被忽略。
总结
this instanceof fNOP && oThis 这一行代码确保了 bind 函数的行为符合预期,无论是直接调用还是作为构造函数使用。通过这种方式,bind 可以正确地处理 this 的绑定,无论是在普通函数调用还是构造函数调用的情况下。
bind返回的函数在作为构造函数的时候this instanceof fNOP会是true,否则就是false。
在Function.prototype.bind实现中,第12行的条件this instanceof fNOP && oThis用于处理使用new操作符调用绑定函数的情况。具体来说:
this instanceof fNOP检查当前的this是否为fNOP的实例。&& oThis确保oThis参数不为undefined或null。
这两部分结合起来是为了确保当fBound被用作构造函数(即通过new操作符调用时),this指向的是新创建的对象实例,而不是oThis。
示例代码
function foo(a, b) {
this.a = a;
this.b = b;
}
const boundFoo = foo.bind(null, 1);
// 使用 new 调用
const instance = new boundFoo(2);
console.log(instance.a); // 输出: 1
console.log(instance.b); // 输出: 2
// 直接调用
const result = boundFoo(2);
console.log(result); // 输出: undefined (因为foo没有返回值)
在这个例子中:
- 当通过
new boundFoo(2)创建实例时,this指向新创建的对象实例。 - 当直接调用
boundFoo(2)时,this指向null,因此a和b属性会添加到全局对象(浏览器环境下的window对象)上。
这样做的目的是为了确保当fBound作为构造函数使用时,其内部的this能够正确地指向新创建的对象实例。

