javaScript继承方法

73 阅读1分钟

共享原型

  • 通过将子类(实例的构造函数)指向父类(原型链上的原型),然后通过原型链的寻找实现继承
    • 但是这样会导致子类和父类指向同一个地址空间,子类的修改时也会父类的修改
    function Father() {}
    function Son() {}
    Father.prototype.Name = 'Father-prototype-Name'
    Son.prototype = Father.prototype 

    var son = new Son()
    console.log(Son.prototype,Father.prototype)
    Son.prototype.Name = 'modify-Name' // 修改子类(Son原型)上属性
    console.log(Son.prototype,Father.prototype)

)

image.png

圣杯模式

  • 通过创建一个对象,然后将该对象构造函数的原型(F.prototype)指向父类(Origin.prototype),再将子类的原型(Target.prototype)指向此对象(new F())
    function inherit(Target,Origin) {
        // Target extends Origin
        var F = Function(){}
        F.prototype = Origin.prototype
        Target.prototype = new F()
        Target.prototype.constructor = Target // 记录实列化对象的构造函数-子类
        Target.prototype.uber = Origin.prototype // 记录继承的父类
    }
  • 通过立即执行函数将 函数F 私有化
    var inherit = (function(){
        
        var F = function(){}
        return function(Target,Origin) {
            F.prototype = Origin.prototype
            Target.prototype = new F()
            Target.prototype.constructor = Target
            Target.prototype.uber = Origin.prototype
        }
    })()
  • 未继承时关系如下图所示

image.png

  • 继承后关系如下图所示 image.png

  • 那可以将 F.prototype = Origin.prototypeTarget.prototype = new F() 互换位置吗 ?

    • 显然是不可以的,因为这样Target.prototype 指向实例化匿名对象,因为此时 函数F 的prototype还未修改,所以这时候创建的 实例化对象的__proto__属性指向Object.prototype,而非Origin.prototype
    • 如下图所示

image.png

总结

  • javaScript的继承是通过原型链上的原型实现的,需要注意的是prototype属性它指向的是一个地址空间,还有F.prototype = Origin.prototypeTarget.prototype = new F()的先后问题