ES5 / ES6 的继承

83 阅读2分钟

ES5的继承

1. 原型链继承  (子类的原型是父类的实例)
    
    function Super(name) {
        this.name = name;
    }
    
    function Child() {}
    
    Child.prototype = new Super('李四');
    
    优点:
        · 继承了父类的模版,又继承了父类的对象
    
    缺点:
        · 值共享
        · 无法向父类的构造函数传参
        · 无法实现多继承
                    
    
2. 构造函数继承
    // 通过call、apply继承父类构造函数内的属性和方法
    function Super(name) {
        this.name = name;
    }
    
    function Child (name) {
        Super.call(this, name)
    }
    
    优点:
        · 解决了子类向父类传参
        · 可以实现多继承
        · 解决了原型链继承中,子类修改父类属性和方法的问题。
    
    缺点:
        · 无法继承父类原型上的属性和方法。
        · 每个新实例都有父类的副本,无法复用,臃肿。
    

3. 组合继承(原型链继承 + 构造函数继承)

    function Super(name) {
        this.name = name;
    }
    
    function Child (name) {
        Super.call(this, name)
    }
    
    Child.prototype = new Super('里斯')
    
    优点:
        · 可以继承实例属性/方法,
        · 也可以继承原型属性/方法,不存在引用属性共享问题,可传参,可复用
    
    缺点:
        · 两次调用父类的构造函数(耗内存)

4. 原型式继承  (将子类的原型设置为父类的原型)

    function Super(name) {
        this.name = name;
    }
    
    function Child (name){
        Super.call(this, name)
    }
    
    function inherit(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    
    const supe = new Super('里斯')
    const b = inherit(supe);
    
    缺点:
        · 无法复用
        · 所有实例都会继承原型上的属性
    
5. 寄生组合式继承(常用)
    
    function Super(name) {
        this.name = name;
    }
    
    function Child(name){
        Super.call(this, name)
    }
    
    Child.prototype = Object.create(Super.prototype)
    Child.prototype.constructor = Child;
    
    优点 :既可以传参又实现了原型的复用
    

ES6的继承

    使用extends实现继承,原理和寄生组合式继承一样。
    

ES5 ES6 继承的不同

    ES5 ES6 子类 this 生成顺序不同。
    
    ES5 先生成了子类实例,再用父类构造函数修饰子类实例
    
    ES6 先生成父类实例,在用子类构造函数修饰父类实例
    
    这个差别使得 ES6 可以继承内置对象。