Skip to content

前言

该死的八股文,问八股文的公司都是lj。

类继承

通过原型链继承,缺点有两个,原型是复制模式,当修改一个原型链的引用类型时,会直接到原型链上修改,间接的影响其他依赖原型链的对象,第二个是没法在创建子类时自定义父类的构造器参数

js
function Human(name) {
    this.name = name
}
Human.prototype = {
    speak() {
        console.log(this.name)
    },
}
Human.prototype.constructor = Human; // 重写了原型,将构造函数补全

function Man(sex) {
    this.sex = sex
}
Man.prototype = new Human();
Man.prototype.constructor = Man; // 修正constructor

const ming = new Man();
ming.speak()
ming.speak.test // undefined
const ku = new Man();
ku.speak.test = 'ku'
ming.speak.test // 影响了同级的子类

构造函数继承

为了解决上面问题,衍生出了构造函数继承的方案、但是这种方案总是会将父对象拷贝一份,在大量子类时不满足共享原则,其二父类原型上的方法没有继承到

js
function Human() {
    this.speak = function() {
        console.log(this.name)
    }
}
function Man(sex, name) {
   Human.call(this, name);  // 每次Human() 执行都会创建一个新的speak,可以随意修改不会影响
   this.sex = sex;  // 同时 也会将speak绑定到speak上
}

组合式继承

为了解决上面父类原型没有继承到子类的问题,组合式继承就是构造函数继承和类继承的结合。缺点也有就是父构造函数会执行两次,对于父构造函数开销比较大比较耗时

js
function Human(name) {
    this.name = name
}
Human.prototype.speak = function() {
    console.log(this.name)
}

function Man(sex, name) {
    Human.call(this, name)
    this.sex = sex
}

Man.prototype = new Human();
Man.prototype.constructor = Man;

原型式继承

这种就是创建实例,没有了类那一套继承逻辑(然而,类不也是为了创建实例),这个缺点也是如果o上面有引用的属性,继承o的所有值会共享。Object.create() 就是这玩意儿

js
function inheritObject(o) {
    function F() {}
    F.prototype = o;
    return new F
}

寄生式继承

其实就是原型式继承的函数封装,新增了扩展子对象的方法

js
function createBook(book) {
    const o = new inheritObject(book);  // 有new和无new有没有区别
    o.jump = function() {} // 添加了子对象独有的方法
}

寄生组合式继承

上面都是直接针对对象的,如果是类就该用下面这种

js
function inheritClass(subClass, superClass) {
    // 拷贝父的原型
    const p = inheritObject(superClass);
    subClass.prototype = p;
    subClass.prototype.constructor = subClass;
}

function SubType() {
    SuperType.call(this)
}
inheritClass(SubType, SuperType)