🌟 先说一句话总结:
这张图展示的是:当你创建一个对象时,它如何通过
__proto__一层层向上找属性和方法,直到最后的null。
🔍 第一步:认识图中的角色
我们先看看图里有哪些东西:
- Person (构造函数)
→ 就是一个普通的函数,用来“制造”人(对象)的模板。 - Person.prototype
→ 是Person函数自带的一个“原型对象”,所有由Person创建的对象都会继承它的属性和方法。 - person(实例)
→ 是用new Person()创建出来的具体对象,比如小明、小红。 - Object()
→ JavaScript 中所有对象的“祖宗”,所有对象都来自它。 - Object.prototype
→ 所有对象的最终原型,它包含一些通用的方法,比如toString()、hasOwnProperty()等。 - null
→ 最终的终点,表示没有再往上找了。
🧩 第二步:画出关系,像搭积木一样
我们从上到下看:
✅ 1. Person 和 Person.prototype 之间的关系
Person是一个构造函数。- 它有一个属性叫
prototype,指向Person.prototype(这个是系统自动给的)。 - 而
Person.prototype也有一个属性叫constructor,指向Person构造函数。
👉 就像:
“我(Person)的 prototype 是 Person.prototype,而 Person.prototype 的 constructor 是我。”
这形成一个双向链接,就像两个朋友互相指着对方。
✅ 2. person 实例 和 Person.prototype 的关系
- 当你写
var person = new Person();时,会创建一个新对象person。 - 这个
person对象内部有一个隐藏的属性叫__proto__,它指向Person.prototype。
👉 就像:
“我是 person,我的爸爸是 Person.prototype。”
所以,当你访问 person.name 时,如果 person 没有这个属性,就会去 Person.prototype 里找。
✅ 3. Person.prototype 和 Object.prototype 的关系
Person.prototype本身也是一个对象(它是Object的实例)。- 所以它也有自己的
__proto__,指向Object.prototype。
👉 就像:
“我是 Person.prototype,我的爷爷是 Object.prototype。”
✅ 4. Object.prototype 和 null
Object.prototype是所有对象的终极祖先。- 它的
__proto__指向null,表示“到这里为止了”。
👉 就像:
“我是 Object.prototype,我没有爸爸了,尽头就是 null。”
🔄 第三步:举个例子,让你完全明白
假设我们写代码:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("你好,我是" + this.name);
};
var person = new Person("小明");
现在我们来看看 person 到底能访问哪些东西:
-
person.name→ 找到了!在person自己身上。 -
person.sayHello()→ 找不到?别急!- 它会去
person.__proto__(也就是Person.prototype)找。 - 发现有
sayHello方法!执行成功!
- 它会去
-
person.toString()→ 也没定义?- 先去
Person.prototype找 → 没有。 - 再去
Person.prototype.__proto__(也就是Object.prototype)找 → 有! - 所以可以调用
toString()。
- 先去
-
person.__proto__.__proto__.__proto__→ 最后是null,停止查找。
📌 总结:原型链是什么?
原型链 就是:当一个对象找不到某个属性或方法时,就沿着
__proto__向上一层层找,直到找到或者到null为止。
就像你问:“我爸是谁?”
→ 爸说:“我爸爸是爷爷。”
→ 爷爷说:“我爸爸是太爷爷。”
→ 太爷爷说:“我没有爸爸了。”(null)
🎯 图解关键点(再看一遍图)
Person (构造函数)
↓
person (实例)
↘ __proto__ → Person.prototype (实例原型)
↓ __proto__ → Object.prototype
↓ __proto__ → null
同时:
Person.prototype.constructor === PersonObject.prototype.constructor === ObjectPerson.prototype.__proto__ === Object.prototype
💡 小贴士(帮你记牢)
| 名称 | 是什么? | 类比 |
|---|---|---|
Person | 构造函数 | 工厂 |
Person.prototype | 原型对象 | 工厂的标准图纸 |
person | 实例对象 | 用图纸造出来的产品 |
__proto__ | 隐藏指针 | “我的爸爸是谁?” |
Object.prototype | 最终祖先 | 老祖宗 |
null | 终点 | “没爸爸了” |
✅ 最后测试一下你懂了吗?
问:person 能不能用 toString()?
答:
person自己没有 → 查__proto__→Person.prototype没有 → 查Person.prototype.__proto__→Object.prototype有!✅
所以可以!
如果你还是觉得晕,没关系!
你可以把这张图当成一棵树:
null
↑
|
Object.prototype
↑
|
Person.prototype
↑
|
person
从下往上走,就是原型链!
🧠 记住口诀:
“实例找原型,原型找父原型,一直找,直到 null。”