JS 的几种继承模式
1 原型链模式
function FatherType() {
this.colors = ['red', 'green', 'blue']
}
function SonType() { }
SonType.prototype = new FatherType()
let son = new SonType()
son.colors.push('black')
console.log(son.colors);
let son1 = new SonType()
console.log(son1.colors);
问题:
- 原型中包含的引用值会在所有实例间共享。
- 子类型在实例化时不能给父类型的构造函数传参。我们无法在不影响所有对象实例的情况下把参数传进父类的构造函数。
2 盗用构造函数模式
基本思路:在子类的构造函数中调用父类的构造函数。
function FatherType(name) {
this.colors = ['red', 'green', 'blue']
this.name = name
}
function SonType(name) {
FatherType.call(this, name)
this.age = 12
}
let son = new SonType('li')
son.colors.push('black')
console.log(son.colors);
let son1 = new SonType('zhang')
console.log(son1.colors);
console.log(son.name, son.age);
console.log(son1.name, son1.age);
优点:可以在子类构造函数中向父类构造函数传参。
问题:
- 必须在构造函数中定义方法,因此函数不能重用。
- 子类不能访问父类原型上的方法。
3 组合继承
组合继承(经典继承)综合了原型链和盗用构造函数。
基本思路:使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。
function FatherType(name) {
this.colors = ['red', 'green', 'blue']
this.name = name
}
FatherType.prototype.say = function () {
console.log(this.name);
}
function SonType(name, age) {
FatherType.call(this, name)
this.age = age
}
SonType.prototype = new FatherType()
SonType.prototype.sayAge = function () {
console.log(this.age);
}
let son = new SonType('li', 12)
son.colors.push('black')
console.log(son.colors);
son.say()
son.sayAge()
let son1 = new SonType('zhang', 23)
console.log(son1.colors);
son1.say()
son1.sayAge()
4 寄生式组合继承
组合继承存在效率问题:父类构造函数始终会被调用两次,一次是在创建子类原型时调用,一次是在子类构造函数中调用。
基本思路:不通过调用父类构造函数给子类原型赋值,而是取的父类原型的一个副本。
function object(o) {
function F() { }
F.prototype = o
return new F()
}
function inheritPrototype(sonType, FatherType) {
let prototype = object(FatherType.prototype)
prototype.constructor = sonType
sonType.prototype = prototype
}
function Father(name) {
this.colors = ['red', 'green', 'blue']
this.name = name
}
Father.prototype.sayName = function () {
console.log(this.name);
}
function Son(name, age) {
Father.call(this, name)
this.age = age
}
inheritPrototype(Son, Father)
Son.prototype.sayAge = function () {
console.log(this.age);
}
寄生式组合继承可以算是引用类型继承的最佳模式。
参考文献
[1] (美) 马特·弗里斯比(Matt Frisbie)著. 李松峰译. JavaScript高级程序设计: 第4版[M]. 人民邮电出版社, 2020.9
|