JavaScript中的继承方式

159 阅读2分钟

《JavaScript高级程序设计》 162-173页,算是自己理解的一点总结,可能有很多地方会有错误和不严谨的地方,希望能有大佬帮忙指出。 想要更加深入了解相关知识推荐直接阅读此书

原型链继承

创造一个将要继承的实例放入原型中,所有子类共享继承的属性。

    function Parent(){
        this.friends = ['sun']
        this.age = 11
    }
    Parent.prototype.sayHello = function(){
        console.log('hello')
    }
    function Child(name){
        this.name = name
    }
    Child.prototype = new Parent() //实现继承
    // 重写原型后会丢失constructor
    Child.prototype.constructor = Child

问题1:父类引用类型被所有实例共享;
问题2:创建Child实例时不能向Parent传参。

构造函数继承

在子类的构造函数执行父类的构造函数,使用call绑定父类的this,并且可以向父类传参。

    function Parent(name){
        this.name = name
        this.friends=['sun']
    }
    Parent.prototype.sayHello = function(){ //无法被继承
        console.log('hello')
    }
    function Child(name){
        Parent.call(this, name)
    }

相对原型链继承来说,构造函数继承在每个子类实例上都有一份独立的父类属性,相互独立。 问题:父类原型无法被继承,因此父类的方法不能写在原型中,只能写在构造函数中。

组合继承

原型和构造函数相结合,是 JavaScript 中最常用的继承模式

    function Parent(name){
        this.name = name
        this.friends=['sun']
    }
    Parent.prototype.sayHello = function(){ //无法被继承
        console.log('hello')
    }
    function Child(name){
        Parent.call(this, name) //一次
    }
    Child.prototype = new Parent() //两次
    // 重写原型后会丢失constructor
    Child.prototype.constructor = Child

问题:父类构造函数执行了两次,子类实例中的属性和原型中有重复。

寄生组合式继承

为了解决组合继承父类的构造函数会执行两边的问题,提出了寄生组合式继承。
在组合继承中,我们在希望子类原型中继承父类,因此在子类的原型中执行了父类的构造函数,实际上我们仅仅是需要父类原型的一个副本而已,并不需要完整的父类。

    function inheritPrototype(Child, Parent){
        let prototype = Object.create(Parent.prototype) //prototype.__proto__ = Parent.prototype
        prototype.constructor = Child // 重写prototype会丢失constructor
        child.prototype = prototype // 实现继承
    }

以上代码实现了对父类原型的拷贝和继承,我们只需要在组合继承中吧继承父类原型的部分替换为以上代码就实现了寄生组合继承。

    function Parent(name){
        this.name = name
        this.friends=['sun']
    }
    Parent.prototype.sayHello = function(){ //无法被继承
        console.log('hello')
    }
    function Child(name){
        Parent.call(this, name) //一次
    }
    // Child.prototype = new Parent() //两次
    // Child.prototype.constructor = Child
    // 替换为
    inheritPrototype(Child, Parent)

寄生组合继承只使用了一次Parent构造函数,而且避免了在Child.prototype上创造重复的东西。