见MDN的代码段,
// 维护原型关系
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
我很疑惑:
问题1:此处为什么要判断 if (this.prototype) {
而不是直接指定 fNOP.prototype = this.prototype;
?
我观察发现,Function.prototype也是个函数(有这个函数才有的Function 这个构造方法),也有bind方法,但没有prototype,所以要加判断,其实不加也没毛病;
问题2:为什么此处要多一个 fNOP 作为中转函数?
答案: 本来bound.prototype = self.prototype
就可以将原属性集成过来了,但是这样两个对象属性都指向同一个地方,修改 bound.prototype 将会造成self.prototype 也发生改变,这样并不是我们的本意。所以通过一个空函数 nop 做中转,能有效的防止这种情况的发生。
比如见如下代码段:
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,
fBound = function () {
console.log("21:53", fBound, this, this instanceof fBound);
return fToBind.apply(this instanceof fBound
? this
: oThis,
// 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fBound.prototype = this.prototype; //直接赋值prototype
return fBound;
};
function Foo() {
this.name = 'Lily';
}
Foo.prototype = { age: 90 };
var fn = Foo.bind({}, 123);
var p1 = new fn();
console.log(p1.age); // 90
fn.prototype.age = 70; // 不小心更改了 生成的函数的原型,导致原来的函数的原型也被修改
console.log(p1.age); // 70
var fn1 = Foo.bind({}, 1234);
var p2= new fn1();
console.log(p2.age); // 70 原型链被修改了 被影响了 这不是我期望的结果
如上,如果没有fNOP为中介,有人更改了生成的函数的原型,会导致原来的函数的原型也被修改。所以 需要一个fNOP为中介。