前端学习系列——(十)JavaScript的继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_36521655/article/details/81118465

这里主要讲4种ES5继承以及ES6的class语法糖的继承。

这里给出父类的定义:

function SuperType(name) {
    this.name = name;
}

SuperType.prototype.sayName = function () {
    console.log(this.name);
};

1、原型链继承

核心:将父类的实例作为子类的原型

function SubType(name) {
    this.name = name;
}

SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;

此时原型对象的constructor的执行变成了SuperType,因为constructor指向构造函数,所以重新指向子类的构造函数即可,即Subtype.prototype.constructor = SubType;

优点

1)非常纯粹的继承关系,实例是子类的实例,也是父类的实例,通过instanceof可以判断

2)父类新增原型方法/属性,子类都可以访问到

3)简单、易于实现

缺点

1)要想子类新增属性和方法,必须要在new SuperType()这样的语句之后执行,不能放到构造函数中

2)无法实现多继承

3)来自原型对象的引用属性是所有实例共享的

4)创建子类实例时,无法向父类构造函数传参

2、构造函数继承

核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类,在子类的构造函数内使用SuperType.call(this);

function SubType(name) {
    SuperType.call(this, name);
}

优点

1、解决了原型链继承中,子类实例共享父类属性的问题

2、创建子类实例是,可以向父类传递参数

3、可以实现多继承(call多个父类对象)

缺点

1、实例并不是父类的实例,只是子类的实例(instanceof可以判断)

2、只能继承父类的实例属性和方法,不能继承原型属性/方法

3、无法实现函数服用,每个子类都有父类的实例函数的副本,影响性能

3、组合继承(构造函数继承和原型链继承的结合)

核心:在构造函数内利用call方法,直接调用属性,然后在原型prototype上绑定绑定方法(通过实例化new父对象),然后修改constructor指向子对象的构造函数。

function SubType(name){
    SuperType.call(this,name);//第二次调用父类
}
SubType.prototype = new SuperType();//第一调用父类
SubType.prototype.constructor = SubType;

优点

1、既是子类的实例,也是父类的实例

2、不存在引用属性共享问题

缺点

1、调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

4、寄生组合继承(目前最优)

核心:通过寄生方式,砍掉父类的实例属性,这样在调用两次父类的构造函数的时候,就不会初始化两次实例方法/属性,避免了组合继承的缺点

function SubType(name) {
    SuperType.call(this,name);
}

(function () {
    var Super = function () {
        //创建没有实例的方法的类
    };
    Super.prototype = SuperType.prototype;
    SubType.prototype = new Super();//将实例作为子类的原型
    SubType.prototype.constructor = SubType;
})();

5、ES6继承

核心:通过ES6语法糖class,使用extends关键字

class SubType extends SuperType{
    constructor(...args){
        super(...args);
    }
}

通过在class的constructor方法内调用super,调用父类的constructor方法,用于新建父类的this对象。

SubType.__proto__ === SuperType;//true
SubType.prototype.__proto__ === SuperType.prototype;//true

只要带有prototype属性的函数就能被extends关键字继承

部分内容参考《JS高级程序设计第三版》和《ES6标准入门第三版》

猜你喜欢

转载自blog.csdn.net/sinat_36521655/article/details/81118465