原型链继承
本质:<font color="#7dcdc2">重写原型对象,指定为新的类型的实例。</font>
父类Person 和 子类Student,通过原型链继承需要设置 <font color="#7dcdc2">Student.prototype = new Person()</font>
instanceof 原理就是一层层查找 __proto__,如果 和 constructor.prototype 相同返回 true。
<font color="#f68b1f">缺点</font>
<font color="#f68b1f">引用类型</font>会被多个实例所<font color="#f68b1f">共享</font>,数据被篡改。例如:数组(<font color="#f68b1f">引用类型被共享</font>)
<font color="#f68b1f">子类原型上的 constructor 方法被重写,</font>Student.prototype.constructor != Student (<font color="#f68b1f">原型constructor被重写</font>)
必须在重置原型后向子类添加属性和方法,否则会被覆盖丢失(<font color="#f68b1f">原型覆盖问题</font>)。
无法向父类的构造函数传参(<font color="#f68b1f">无法传参</font>)
借用构造函数继承
本质:<font color="#7dcdc2">使用父类的构造函数增强子类实例,等同于<b>复制父类的实例给子类</b></font>。
子类 Student 中执行父类构造函数 <i><font color="#fac6d2">S</font><font color="#f68b1f">uperType.call(this)</font></i>,子类的每个实例都会将父类的属性复制一份。
缺点
只能继承父类的实例属性和方法,无法继承原型的。
无法实现复用,每个子类实例都存在父类的副本
组合继承
<font color="#55beed"><i>原型链 </i>实现原型属性和方法的继承,<i>借用构造函数 </i>实现实例属性的继承。</font>
缺点:调用<font color="#7dcdc2">两次父类的构造函数</font>,子类的实例和原型上都存在相同的父类属性和方法 (<font color="#f68b1f">调用两次父类构造函数</font>)
原型式继承
利用一个<font color="#7dcdc2">空对象</font>作为中介,将某个对象直接赋值给空对象构造函数的原型。
缺点
原型链继承多个实例的<font color="#7dcdc2">引用类型属性指向相同</font>,存在篡改的可能。<br>
无法传递参数
<b><font color="#f15a23">寄生式组合模式</font></b>
特点:
结合<b><font color="#55beed">借用构造函数传递参数</font></b>和<b><font color="#55beed">寄生模式实现继承</font></b>
<font color="#7dcdc2">只调用一个父类的构造函数,原型链保持不变</font>
<font color="#f384ae">这是最成熟的方法,也是现在库实现的方法</font>
ES6继承extends
extends继承的核心代码实现和上述的寄生组合式继承方式一样