首先来个两个构造函数 Parent,Child
function Parent (a) {
this.a = a
}
function Child (a, b) {
this.a = a
this.b = b
}
const child = new Child('aa', 'bb')
console.log(child) // {a: 'aa', b: 'bb'}
简单继承改造
function Parent (a) {
this.a = a
}
function Child (a, b) {
Parent.call(this, a)
this.b = b
}
const child = new Child('aa', 'bb')
console.log(child) // {a: 'aa', b: 'bb'}
但是给父的原型上添加方法,执行child.fn()会报错,说明原型上的值或方法没有被继承
function Parent (a) {
this.a = a
}
Parent.prototype.fn = function () {
console.log('fn')
}
function Child (a, b) {
Parent.call(this, a)
this.b = b
}
const child = new Child('aa', 'bb')
console.log(child) // {a: 'aa', b: 'bb'}
child.fn() // Uncaught TypeError: child.fn is not a function
执行child.fn()的步骤:
- 在
child自己身上找fn方法,发现没有,再去child.__proto__上找,没有找到会依次找child.__proto__.__proto__、child.__proto__.__proto__.__proto__、...,这就是所谓的原型链; - 我们再看
child.__proto__是什么?其实child.__proto__ === Child.prototype; Child.prototype这个上面也没有fn,fn存在Parent.prototype上,这样就好办了,我让Child.prototype.__proto__ = Parent.prototype那就可以找到fn了;
所以加上这行代码Child.prototype.__proto__ = Parent.prototype
function Parent (a) {
this.a = a
}
Parent.prototype.fn = function () {
console.log('fn')
}
function Child (a, b) {
Parent.call(this, a)
this.b = b
}
Child.prototype.__proto__ = Parent.prototype
const child = new Child('aa', 'bb')
console.log(child) // {a: 'aa', b: 'bb'}
child.fn() // fn
这样就不报错了,可以找到fn执行了。
但是不推荐直接修改对象的__proto__属性,推荐用Object.setPrototypeOf()方法
改造代码
function Parent (a) {
this.a = a
}
Parent.prototype.fn = function () {
console.log('fn')
}
function Child (a, b) {
Parent.call(this, a)
this.b = b
}
// Child.prototype.__proto__ = Parent.prototype
Object.setPrototypeOf(Child.prototype, Parent.prototype)
const child = new Child('aa', 'bb')
console.log(child) // {a: 'aa', b: 'bb'}
child.fn() // fn