引言 整理自慕课网双越老师课程。
需要明白一些基础概念:
- 如何class一个类
- 如何继承一个类
- 如何创建一个实例
- 什么是原型
- 明白了什么是原型,那原型链是否可以理解为多个原型形成的一条链路
原型
我们通过class一个类并且new这个类来理解下原型。
我们创建了Student的类,定义了一些参数和方法。
class Student {
constructor(name, number) {
this.name = name
this.number = number
}
sayHi() {
console.log(
`姓名 ${this.name} ,学号 ${this.number}`
)
}
}
然后定义xialuo去实例化Student这个类,并且打印输出一些值。
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
可以看到我们成功打印出了夏洛以及100,并且可以成功调用Student里的方法。
再打印下xialuo看看到底是什么。
打印结果看到了xialuo有了Student的参数,并且还有一个__proto__(隐式原型),展开__proto__会发现其实就是我们创建的Student(理解为 prototype 显式原型),包括constructor,SayHi()和另外一个__proto__(这个暂且不讲,涉及到原型链。)
以上就是一个原型啦,总结一下:
- 每个class(Function)都有显式原型 prototype
- 每个实例对象都有隐式原型__proto__
- 实例对象的隐式原型指向class的显示原型
原型链
理解了原型,那么原型链就很好理解了。举个例子:
创建一个父类People
// 父类
class People {
constructor(name) {
this.name = name
this.age = 20
}
eat() {
console.log(`${this.name} eat something`)
}
}
再创建一个子类Student继承父类People,也就是extends的概念,简而言之能继承父类的方法和变量等。
// 子类
class Student extends People {
constructor(name, number) {
super(name)
this.number = number
}
sayHi() {
console.log(`姓名 ${this.name} 学号 ${this.number}`)
}
}
如之前的原型一样,去实例化Student。
// 实例化
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.age)
console.log(xialuo.number)
xialuo.sayHi()
xialuo.eat()
打印一下看看,发现可以打印出父类的变量name age、子类的变量number,父类的方法eat(),子类的方法sayHi(),为啥能访问到呢,这就要靠原型链了。
再打印下实例xialuo看看是什么。
跟原型一样,xialuo有隐式原型__proto__,内容是子类Student的显式原型prototype,这也就是为什么xialuo可以打印出子类的方法和变量。
同时可以发现子类的Student也有隐式原型__proto__,内容是父类People的显式原型prototype,这也就是为什么xialuo可以打印出父类类的方法和变量。
截取老师视频中的关于原型链的简图。
以上就是一个原型啦,总结一下:
- 访问一个对象的属性时,先在自身属性中查找,找到返回;
- 如果没有,再沿着__proto__(隐式原型属性)这条链向上查找,找到返回;如果最终没有找到则返回undefined.
- 因为原型链是沿着__proto__(隐式原型属性)查找,所以又叫隐式原型链.原型链的作用是查找对象属性(方法)的.
- 从打印信息中不难看出,最终原型原型链都指向对象Object。
第一篇文章,希望能坚持记录下去。