1

es6的extends class

class Person {
    constructor(gender) {
        this.gender = gender;
    }
    say(msg) {
        console.log(msg);
    }
}

class Teacher extends Person {
    constructor(age) {
        super('male');
        this.age = age;
    }
}

const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') //hello

原型链继承

function Person(gender) {
    this.gender = gender;
}

Person.prototype.say = function(msg) {
    console.log(msg);
}

function Teacher(age) {
    this.age = age;
}

Teacher.prototype = new Person('male');

const mike = new Teacher(26);
// mike.__proto__ === Teacher.prototype === p
// p.__proto__ === Person.prototype
mike.age // 26
mike.gender // male
mike.say('hello') //hello
  • 这种方式的继承,不能动态给父类传参,一旦建立联系,就必须确认new Teacher时的入参;
  • 同时由于是直接把父类实例付给子类原型,后续子类的所有实例都共享父类实例中的属性,即任何一个子类实例修改gender都会影响其他实例

构造函数继承

function Person(gender) {
    this.gender = gender;
}

Person.prototype.say = function(msg) {
    console.log(msg);
}

function Teacher(age) {
    this.age = age;
    Person.call(this, 'male')
}

const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // 报错
  • 父类上的属性可以绑定到子类实例上,由于是直接挂载在实例,而非实例原型上,故属性不会相互影响
  • 但该方法并没有将原型链关联,即无法从子类找到父类,且子类实例无法访问父类原型链上的方法

组合继承

function Person(gender) {
    this.gender = gender;
}

Person.prototype.say = function(msg) {
    console.log(msg);
}

function Teacher(age) {
    this.age = age;
    Person.call(this, 'male');
}

Teacher.prototype = new Teacher('female');

const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
  • 组合使用原型链继承和构造函数继承
  • 可以同时继承父类属性和父类原型链上的属性
  • 由于实际相当于调用了两次父类的构造函数,开销比其余方式大,同时gender属性因为会同时挂载在子类实例上,以及子类的原型上,前者会遮蔽后者,且前者在实例间不会相互影响,但后者就显得多余了

寄生继承

function Person(gender) {
    this.gender = gender;
}

Person.prototype.say = function(msg) {
    console.log(msg);
}

function Inherit(Parent, age) {
    const obj = Object.create(new Parent('male'));
    // obj.__proto__ === p
    // p.__proto__ === Parent.prototype
    obj.age = age;
    return obj;
}

const mike = Inherit(Person, 26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
  • 寄生顾名思义就是,创建一个对象实现继承,再在其上,加上各种属性
  • 这种方式继承方法通常无法复用,需要更改属性的时候,就要修改方法
  • 同原型链继承,该模式下,子类实例共用父类属性,会相互影响

寄生组合继承

function Person(gender) {
    this.gender = gender;
}

Person.prototype.say = function(msg) {
    console.log(msg);
}

function Teacher(age) {
    const obj = Object.create(Person.prototype);
    // obj.__proto === Person.proptype
    Person.call(obj, 'male');
    obj.age = age;
    return obj;
}

const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
  • 结合组合继承和寄生继承的特点,其中,直接让子类实例的原型指向父类原型,采用object.create而非new一个父类实例,避免了执行两次父类的构造方法
  • 同时由于Teacher会返回一个对象,根据new的执行原理,如果构造函数返回一个对象,会以该对象作为实例后的返回

zengrc
28 声望0 粉丝