说明原型链之前,需要先搞明白一个问题,这个东西产出是来自于哪里?怎么回事?
先看1-5点 是如何产生的原型链,再具体分析类比
( proto prototype以及null三者关系)
一、场景:要造很多个学生(案例说明)
// 1. 构造函数 = 一个"模具"
function Student(name, age) {
this.name = name // 每个学生自己独有的属性
this.age = age
}
// 2. 共用方法放到 prototype(全家共享仓库,只存一份)
Student.prototype.sayHello = function() {
console.log('我是' + this.name + ',今年' + this.age)
}
// 3. 用 new 批量"压"出对象
const s1 = new Student('小明', 18)
const s2 = new Student('小红', 20)
二、这一步背后自动发生了什么
new Student() 时,JS 自动做了三件事:
- 造一个空对象
{} - 把你的属性塞进去 :
{ name: '小明', age: 18 } - 偷偷发一张 "找仓库" 的小纸条 :
s1.__proto__ = Student.prototype
也就是说:每个学生对象身上都自动带着 __proto__,指向 Student.prototype 这个共享仓库。
三、调用方法时发生了什么
s1.sayHello()
- 先看 s1 自己身上有没有
sayHello→ 没有(自己只有 name 和 age) - 顺着
__proto__找到Student.prototype→ 有! - 执行。
s2 调用也是一样的路径 ------ 因为所有学生的 __proto__ 都指向同一个 Student.prototype,所以方法只存一份,1000 个学生共用。
四、三者关系一句话
表格
| 角色 | 是什么 | 类比 |
|---|---|---|
构造函数 Student |
模具,批量造对象 | 饼干模具 |
实例对象 s1/s2 |
模具压出来的饼干 | 你吃到的那块饼干 |
Student.prototype |
构造函数附带的 "共享仓库" | 模具旁边贴的 "说明书" |
s1.__proto__ |
饼干身上写着 "说明书在哪" 的小纸条 | 自动印上去的 |
五、完整链(到顶)
s1.__proto__ → Student.prototype.__proto__ → Object.prototype.__proto__ → null
↑ ↑ ↑
学生对象 学生共用仓库 所有对象的爷爷仓库
(toString/valueOf 在这)
Student.prototype.__proto__指向Object.prototype------ 因为 "学生仓库" 本身也是个对象,它也有爷爷- 一直追到
null为止
**具体说明
类比:**
Person.prototype= 你爸本人(那本全家共用的手册)person.__proto__= 你口袋里一张小纸条,上面写着 "我爸住哪儿"
你要找爸,就看小纸条;小纸条上写的地址,就是爸的 prototype。
对应到代码(这是最关键的等式):
function Person(name) {
this.name = name
}
Person.prototype.sayHello = function() {
console.log('你好,我是' + this.name)
}
const person = new Person('小明')
person.__proto__ === Person.prototype // true!
为什么是 true? 因为 new Person() 的时候,JS 自动做了一件事:把 person 身上的 __proto__ 指向 Person.prototype。等于自动给你发了那张 "找爸" 的小纸条。
两个名字,一个东西,别搞混:
表格
| 站在谁的角度 | 这个东西叫什么 | 是干嘛的 |
|---|---|---|
| 构造函数 Person | Person.prototype |
造出来的 "爹模板",放共用方法 |
| 实例对象 person | person.__proto__ |
找爹的地址,指向上面那个模板 |
完整链就是:
person.__proto__ → Person.prototype.__proto__ → Object.prototype.__proto__ → null
↑ ↑ ↑
口袋里的纸条 顺着纸条找到爸 爸的纸条找到爷爷 尽头
记忆口诀:
prototype是爹本身(构造函数造的模板)__proto__是找爹的地址(实例身上的指针)- 两个指向同一个对象,所以
person.__proto__ === Person.prototype永远成立