JavaScript之深入继承
1. 原型链继承
子类如果需要覆盖父类的方法,或者增加父类没有的方法,需要在原型赋值后,再添加到原型上。如果在赋值前重写方法会破坏(重写)之前的原型链。
原型链继承的问题:
- 原型链继承的对象,会在所有实例间共享,会多出一些不必要的属性,如果修改也会影响到其他实例
- 子例在实例化时不能给父类型的构造函数传参
2. 借用构造函数继承
在子类中调用父类构造函数。
1 | function SuperType() { //相当于在子类中运行了父类的初始化代码,每个实例都有自己的属性 |
借用构造函数的问题:
- 必须在构造函数中定义方法,函数不能重用
- 子类不能访问原型上定义的方法
3.组合继承
综合了原型链和构造函数继承,结合优点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
};
1 | function SuperType(name){ |
4. 原型式继承
1 | function object(o) { //大致用代码解释 |
传入一个对象,将对象赋值给这个构造函数的原型,然后返回实例。
ES5增加了一个方法Object.create()用于原型式继承的概念规范化。在只传一个参数时,方法效果与上述object函数相同。
有两个参数时,添加的属性会遮蔽原型对象上的同名属性:
1 | let person = { |
原型式的继承缺点与原型链继承一样。
5. 寄生式继承
与原型式继承相似,创建一个实现继承的函数,以某种方式增强对象,然后返回对象
1 | function createAnother(original){ |
该继承方式具有父类的属性和方法,还能添加新方法和属性。该方法主要关注对象。有个问题是对象添加函数会导致函数难以重用,与构造函数模式类似。
6. 寄生式组合继承
1 | function inheritPrototype(subType, superType) { |
寄生式组合继承主要是创建父类原型的一个副本,然后给返回的对象设置constructor属性,最后将创建的对象赋值给子类型的原型。
该继承方式好处:
- 只调用了一次构造函数
- 避免了子类上用不到的属性
- 效率更高
- 原型链有效