原型链继承
方法
让子类的原型指向父类的实例
CHILD.propotype = new PARENT();
CHILD.constructor = CHILD; // 自带的构造函数会丢失,需要手动添加。
特点
- 不能传递父类的参数。
- 当在一个子类实例中修改父类中引用类型的值时(比如:在数组中
push一个值进去),会影响所有的子类实例。
利用构造函数继承
方法
在子类里面执行父类的构造方法
function CHILD() {
PARENT.call(this);
}
特点
- 只能继承父类中的属性和方法,不能继承父类原型上的属性和方法。
- 相比于原型链继承可以传递父类中的属性。
- 方法都只能放在构造函数中定义,不能起到函数的复用。
组合继承
方法
将原型链继承和利用构造函数继承的方式结合起来使用
function CHILD() {
PARENT.call(this);
}
CHILD.prototype = new PARENT();
CHILD.prototype.constructor = CHILD;
特点
- 因为将原型链和利用构造函数方式结合到了一起,所以可以发挥两者的优点。既能通过原型上定义方法实现函数的复用,又能保证每个实例都有自己的属性。
- 为 js 中最常用的继承方式。
- 实例和原型上存在两份相同的属性。
原型式继承
方法
定义一个函数,在函数内部定义一个临时性的构造函数,然后将传入的对象作为该构造函数的原型,最后返回这个临时构造函数的实例。
function object(obj) {
function F() { };
F.prototype = obj;
return new F();
}
在 ES5 当中,新增了 Object.create() 方法。这个方法有两个参数,只传入一个参数时和上述功能一样。其中第二个参数也是个对象,是为返回的新对象添加而外属性用的。
特点
- 方便,在没有必要创建构造函数,只是想让两个对象保持这种类似的情况下,可以使用。
寄生式继承
方法
与原型式继承紧密相关。定义一个接收一个对象参数的函数,在里面使用原型式继承,并且在得到的对象上加入自己的方法和属性,最后返回这个对象。
function createAnother(original) {
const clone = Object.create(original);
clone.play = function () { // 添加自己的方法
console.log('playing...');
};
clone.grade = 80; // 添加自己的属性
return clone;
}
特点
- 会重复定义方法,导致不能做到函数的复用,效率低。
寄生组合式继承
方法
将寄生式继承和组合式继承相结合的使用。
function inheritPrototype(child, parent) {
const prototype = Object.create(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
function CHILD() {
PARENT.call(this);
}
inheritPrototype(CHILD, PARENT);
特点
- 弥补了组合式继承会有两份相同属性的缺点。可以说是最理想的继承方法。
参考书籍
- 红宝书(JavaScript 高级程序设计);