1.原型链继承

function SuperType() {
this.property = true;
}

SuperType.prototype.getSuperValue = function() {
return this.property;
}

function SubType() {
this.subproperty = false;
}
// 继承 继承的是父类的实例对象作为自己的原型
SubType.prototye = new SuperType();

存在的问题:

  1. 若原型中存在引用值, 则所有实例继承的都是同一引用对象。
  2. 子类实例化时不能给父类传参。

2.盗用构造函数

==解决的问题: 解决原型包含引用值导致的继承问题==

基本思路:在子类构造函数中通过call, apply调用父类的构造函数

function SubType() {
this.colors = ['red', 'blue', 'green'];
}
function SubType() {
// 继承
SuperType.call(this);
}

优点:可以向父类构造函数传参

function SuperType(name){ 
this.name = name;
}
function SubType() {
// 继承 SuperType 并传参
SuperType.call(this, "Nicholas");
// 实例属性
this.age = 29;
}

缺点:必须在构造函数中定义方法,因此函数不能重用。(只继承了属性)


🍅🍅🍅3.组合继承

思路:使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性

缺点:存在效率问题

解决办法:寄生式组合继承

最主要的效率问题是:父类的构造函数始终会被调用两次

一次是在创建子类原型时, 一次是在子类构造函数中

function SuperType(name){ 
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age){
// 继承属性
SuperType.call(this, name);
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
console.log(this.age);
};

==组合继承弥补了原型链和盗用构造函数的不足,是 JavaScript 中使用最多的继承模式==。

而且组合继承也保留了 instanceof 操作符和 isPrototypeOf()方法识别合成对象的能力。


4.原型式继承

function object(o) { 
function F() {}
F.prototype = o;
return new F();
}
<==>
Object.create()

原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合。

但要记住,属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的。


5.寄生式继承

寄生式继承背后的思路类似于寄生构造函数和工厂模式:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象

function createAnother(original){ 
let clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}

寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。

object()函数不是寄生式继承所必需的,任何返回新对象的函数都可以在这里使用。

缺点:

  • 通过寄生式继承给对象添加函数会导致函数难以重用,与构造函数模式类似。

6.寄生式组合继承

寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。

基本思路:不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。

说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型

function inheritPrototype(subType, superType) { 
let prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 赋值对象
}

这个 inheritPrototype()函数实现了寄生式组合继承的核心逻辑。

这个函数接收两个参数:子类构造函数和父类构造函数

在这个函数内部,第一步是创建父类原型的一个副本。然后,给返回的prototype 对象设置 constructor 属性,解决由于重写原型导致默认 constructor 丢失的问题最后将新创建的对象赋值给子类型的原型

instanceof 操作符和isPrototypeOf()方法正常有效。寄生式组合继承可以算是引用类型继承的最佳模式。


参考:

  • JavaScript高级程序设计