JavaScript 继承(ES5)
继承的意思是,我要这个(独立属性),那个(方法)我也要。
原型链 继承
原型链是 JavaScript 主要继承方式。原型链继承就是通过设置子类的原型为父类的实例来继承子类自身没有但又懒得写的属性和方法。
function Super() {}
function Sub() {}
Sub.prototype = new Super();
如上所示,Super 实例可以访问的属性和方法,在 Sub 上都能访问。
原型链有个问题,当父类的属性是引用类型时,子类的就会共享这个引用类型。
function Super() {
this.colors = ["red"];
}
function Sub() {}
Sub.prototype = new Super();
let sub1 = new Sub();
sub1.colors.push("blue");
let sub2 = new Sub();
sub2.colors; // ['red', 'blue']
盗用构造函数 继承
盗用构造函数的意思是,在子类构造函数中调用父类构造函数。
这样,当父类的属性即使是引用类型时,子类的每个实例的属性也是独立的。
function Super() {
this.colors = [];
}
function Sub() {
Super.call(this);
}
let sub1 = new Sub();
sub1.colors.push("red");
let sub2 = new Sub();
sub2.colors; // []
盗用构造函数的问题:
- 子类无法访问父类原型上的方法
- 想继承方法必须在父类的构造函数上定义
组合继承
组合继承是:原型链继承+盗用构造函数继承
- 使用原型链继承原型上的属性和方法
- 通过盗用构造函数继承父类实例属性
function Super() {
this.colors = [];
}
function Sub() {
Super.call(this);
}
Sub.prototype = new Super();
原型式继承
先看原型式继承原理
// o 为浅复制
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
原型式继承意思是,你有一个对象,很多其他对象都想使用你这一个对象的属性和方法。
const one = { colors: [] };
const obj1 = Object.create(one);
const obj2 = Object.create(one);
obj1.colors.push("red");
obj2.colors.push("blue");
obj1.colors; // ['red', 'blue']
核心方法是 Object.create() ,具体使用请参考 MDN
寄生式继承
寄生式继承和原型式继承差不多,不过寄生式继承要额外创建一个函数,增强对象后再返回这个对象。
function createObj(obj) {
const s = Object.create(obj);
s.hello = () => {}; // 增强对象(加属性、加方法)
return s;
}
缺点:增强对象上的方法难以重用。
寄生式组合继承(最佳模式)
寄生式组合继承先通过盗用构造函数继承属性,再使用混合式原型链继承方法。
// subType 子类构造函数 superType 父类构造函数
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function Super() {
this.colors = [];
}
function Sub() {
Super.call(this);
}
inheritPrototype(Sub, Super);