# 继承(委托)
- JS 原型链与继承别再被问倒了 (opens new window)
- 《JavaScript 设计模式与开发实践》 第一章
- Javascript 继承机制的设计思想 (opens new window)
继承(相当于现实世界继承财务,把父亲的积累的财富,给自己使用)(可以写一篇文章了)
# 原型链继承
原型链天然向上寻找不存在与自己的属性
function Father(name = 'father') {
this.name = name
this.garage = ['BMW', 'Benz']
this.wealth = 10000000
}
function Son() {}
Son.prototype = new Father()
Son.prototype.constructor = Son
const son = new Son()
son.wealth
问题:
- 子类无法传参(无法拥有自己的姓名)
- 父类的属性是引用类型,会和子类一同修改(共用同一个车库)
借用构造函数解决上面问题
# 借用构造函数继承 经典继承
call 能够改变 this 的指向 ,所以我们将子类型构造函数的内部调用超类型构造函数
function Father(name = 'father') {
this.name = name
this.garage = ['BMW', 'Benz']
this.wealth = 10000000
}
function Son(name) {
Father.call(this, name) //继承了Father,且向父类型传递参数
}
var son1 = new Son('son1')
son1.garage.push('Land Rover')
console.log(son1)
var son2 = new Son('son2')
son2.garage.push('Land')
console.log(son2)
问题:
- 无法继承之后父类购买的豪宅了 (Father.prototype.house = []无法在子类继承)
# 组合继承
function Father(name = 'father') {
this.name = name
this.garage = ['BMW', 'Benz']
this.wealth = 10000000
}
function Son(name) {
Father.call(this, name)
}
// 原型链关联
Son.prototype = new Father()
Son.prototype.constructor = Son
const son = new Son('son') // 解决传参
Father.prototype.getMoney = function () {
this.wealth++
} // 解决继承(能力增强)
console.log(son.getMoney)
问题:
- 父类的构造函数被调用了两次
- 子类原型上会存在父类实例属性,浪费内存
# 原型式继承
借助原型可以基于已有的对象创建新对象, 同时还不必因此创建自定义类型
//具体的一个示例
const bier = {
name: 'bier',
wealth: 10000000,
garage: ['法拉利', '劳斯莱斯'],
}
function object(obj) {
function F() {}
F.prototype = obj
return new F()
}
const son = object(bier) // 在 ECMAScript5 中,通过新增 object.create() 方法规范化了上面的原型式继承.
const son1 = Object.create(bier)
// son son1 bier公用同一个车库
问题:
- 和原型链继承存在一样的问题
# 寄生式继承
寄生式继承的思路与(寄生)构造函数和工厂模式类似, 即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象. 如下.
const father = {
name: 'bier',
wealth: 10000000,
garage: ['法拉利', '劳斯莱斯'],
}
function createSon1(original) {
var clone = Object.create(original) //通过调用object函数创建一个新对象
clone.sayHi = function () {
//以某种方式来增强这个对象
alert('hi my name is son1')
}
return clone //返回这个对象
}
console.log(createSon1(father))
function createSon2(original) {
var clone = Object.create(original) //通过调用object函数创建一个新对象
clone.sayHi = function () {
//以某种方式来增强这个对象
alert('hi my name is son2')
}
clone.name = 'son2'
return clone //返回这个对象
}
console.log(createSon2(father))
问题:
- 每个不同的增强示例都需要一个创建函数
# 寄生组合继承
又要解决增强问题,又要解决不用调用第二次父类构造函数(增强子类原型) 。不必为了指定子类型的原型而调用超类型的构造函数
Object.create(Parent.prototype)
function Father(name = 'father') {
this.name = name
this.garage = ['BMW', 'Benz']
this.wealth = 10000000
}
function Son(name) {
Father.call(this, name)
}
// 原型链关联
Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son
Father.prototype.getMoney = function () {
this.wealth++
}
const son = new Son(1)