关于bind方法的polyfill问题

见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为中介。

你可能感兴趣的:(关于bind方法的polyfill问题)