画一个原型链的图示,并配合代码进行讲解原型链。
我们先给出用于讲解原型链的class案例:
//父类
class People {
constructor(name) {
this.name = name
}
eat(){
console.log(`${this.name} eat something`)
}
}
//子类
class Student extends People {
constructor(name, number) {
super(name)
this.number = number
}
sayHi(){
console.log(`姓名 ${this.name} 学号 ${this.number}`)
}
}
//通过类声明对象/实例
const xialuo = new Student('夏洛', 100)
首先,我们先分析一下上面创建的class的类型:
// class 实际上是函数,可见是语法糖
typeof People // 'function'
typeof Student // 'function'
(一)在了解了class其实是函数后,我们再了解一下隐式原型和显示原型:
// 隐式原型和显示原型
console.log(xialuo.__proto__) //xialuo是Student的实例
console.log(Student.prototype)
console.log(xialuo.__proto__ === Student.prototype)
查看打印结果:
可以得到一个初步的图示:
(二)接着,我们再次打印:
console.log(Student.prototype.__proto__)
console.log(People.prototype) //People是Student的父类
console.log(Student.prototype.__proto__ === People.prototype)
因此我们可以得到如下的原型关系:
- 子类的prototype的__proto__指向其父类的prototype
可以得到下图:
(三)之后,我们再进一步:
console.log(People.prototype.__proto__)
console.log(Object.prototype)
console.log(People.prototype.__proto__ === Object.prototype)
打印结果如下:
可以得到下图:
总结
原型关系:
- 每个class都有显式原型 prototype
- 每个实例都有隐式原型__proto__
- 实例的__proto__指向对应class的 prototype
基于原型的执行规则:
- 获取属性xialuo.name或执行方法xialuo.sayHI()时
- 先在自身属性和方法寻找
- 如果找不到则自动去__proto__寻找