JS(11)—— 一些个继承 ,很全!

100 阅读3分钟

大致有 6 种 (各有利弊)

  • 原型链继承
  • 盗用(父类)构造函数继承
  • 组合继承【原型链 + 盗用构造函数】
  • 原型继承 【不需要事先创造构造函数】 (工厂)
  • 寄生式继承 【拷贝原对象、增强副本、返回】 (工厂)
  • 寄生式组合继承

<1> 原型链继承

让子类构造函数的原型对象指向父亲的实例对象。即 Child.prototype = new Parent()。这样依据原型链,子类实例对象的原型对象就是父亲的实例对象,就会拥有父类的属性和方法。

缺点:

  • 所有实例共享同一个引用类型的属性
  • 在 new Child() 实例时,不能向 Parent() 构造函数传参

<2> 盗用构造函数继承

在定义子类的构造函数时,在子类构造函数内部调用父类的构造函数,从而将父类属性继承到自己身上。

function Parent () {
this.names = ['kevin', 'daisy'];
}

function Child () {
Parent.call(this);
}
var child1 = new Child();

优点:

  • 避免了引用类型的属性被所有实例共享
  • 可以在 Child 中向 Parent 传参

缺点:

  • 每次创建实例都会创建一遍方法。(且继承不到父亲原型中的方法!!!!

<3> 组合继承【原型链 + 盗用构造函数】

使用原型链继承原型上的属性和方法,使用盗用构造函数继承实例自己的属性!!!

function Parent (name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
    console.log(this.name)
}

function Child (name, age) {

    Parent.call(this, name);
    
    this.age = age;

}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child('kevin', '18');

缺点:

  • 效率问题,父类构造函数被调用了两次!!!

<4> 原型继承 【不需要事先创造构造函数,工厂模式】【适用于没有构造函数,只有想要继承的实例对象】

实现对象间属性和方法的共享,不需要单独创建父类、子类构造函数,也不需要再 new 出来子类的实例对象。思路就是:创建一个空的构造函数 F(),把该构造函数的原型指向要继承的对象。然后返回 new F()

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

缺点:

  • 所有实例共享同一个引用类型的属性

<5> 寄生式继承 【拷贝原对象、增强副本、返回】

基本思路 类似于寄生构造函数和工厂模式:创建一个实现继承的函数,在函数中先拷贝源对象,然后增强副本,然后返回新对象!!

function createObj (o) {
    var clone = Object.create(o);
    clone.sayName = function () {
        console.log('hi');
    }
    return clone;
}
  • 跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

<6> 寄生式组合继承

盗用构造函数继承父类属性。用寄生的方法获取父亲原型的一个副本【不借助父类构造函数,区别于组合式继承】

function Parent (name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
    console.log(this.name)
}
// 盗用构造函数继承属性

function Child (name, age) {
    Parent.call(this, name);
    this.age = age;
}


// 寄生式+原型式 继承方法

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

function prototype(Child, Parent) {
    var prototype = object(parent.prototype);
    prototype.constructor = Child;
    Child.prototype = prototype;
}

// 当我们使用的时候:
prototype(Child, Parent);

优点:

  • 解决了组合继承【盗用构造函数 + 原型链】需要多次 new Parent() 的效率问题!!!