别再混淆了!一张图彻底搞懂 proto 和 prototype 的区别
JavaScript 中的原型(Prototype)和原型链一直是前端学习道路上的“拦路虎”,尤其是 __proto__ 和 prototype 极其相似的命名常常让人混淆。本文不堆砌晦涩的定义,而是通过一个通俗易懂的“Pig 构造函数”实例,配合 Mermaid 流程图,从内存引用的角度为你拆解它们的三角关系。无论你是初学者还是正在准备面试,读完本文,你将能清晰地理解“公共仓库”与“查找线索”的
彻底搞懂 JavaScript 原型与原型链:proto 和 prototype 到底有什么区别?
写在前面:核心结论速读
如果你时间紧迫,请先记住这 3 点核心区别,带着结论去看正文会更清晰:
持有者不同:
prototype属于构造函数(它是模具);__proto__属于实例对象(它是产品)。作用不同:
prototype是“公共仓库”,用来存放**共用方法;__proto__是“线索指针”,用来指向那个仓库。一句话总结:开发者通过
prototype往里存,实例对象通过__proto__往外找。
在学习 JavaScript 的过程中,原型(Prototype)和原型链(Prototype Chain)无疑是最容易让人混淆的概念之一。特别是 __proto__ 和 prototype 这两个属性,名字相似但作用完全不同。
本文将通过一个通俗易懂的例子,并配合图解,帮助大家彻底厘清这两个概念的关系以及背后的查找机制。
1. 从一个具体的例子开始
为了理解这个概念,我们定义一个简单的构造函数 Pig(猪):
JavaScript
function Pig(name, age, father) {
this.name = name;
this.age = age;
this.father = father;
}
// 往原型对象(公共仓库)里添加方法
Pig.prototype.sleep = function() {
console.log(this.name + ' 正在睡觉...');
};
// 创建一个实例对象
const peppa = new Pig('Peppa', 5, 'Daddy Pig');
当我们写下这段代码时,JavaScript 引擎在后台建立了关键的连接。我们需要关注两个核心角色:构造函数和实例对象。
2. 核心关系图解:一张图看懂
在我们深入概念之前,先看这张核心关系图。这是理解一切的基础:
Code snippet
从图中我们可以清晰地看到:
-
左上:构造函数
Pig。 -
中间:公共仓库
Pig.prototype。 -
左下:也就是我们需要关注的实例
peppa。 -
关键点:
peppa和Pig并没有直接的物理连接,它们是通过中间的Pig.prototype关联起来的。
3. 核心概念一:prototype(显式原型)
谁拥有它? 只有构造函数(函数)。
在上面的例子中,Pig 是一个构造函数。在声明这个函数时,JavaScript 会自动给它创建一个属性叫做 prototype。
它的作用是什么?
prototype 是一个对象,我们可以把它理解为一个公共仓库或者模具。它的主要作用是存储所有 Pig 实例都需要共享的属性和方法。
我的理解总结: prototype 是构造函数特有的,它指向一个对象(原型对象),用来存放公共功能。
4. 核心概念二:proto(隐式原型)
谁拥有它? 所有的对象(包括实例对象)。
当我们使用 new Pig() 创建出 peppa 这个实例时,peppa 身上会自动带有一个属性叫做 __proto__。
它的作用是什么?
proto 是一个指针(或线索)。它指向哪里?它指向构造函数的 prototype。
本质上,__proto__ 的存在就是为了让实例对象能够找到它的“出身”,从而访问那个公共仓库里的方法。
JavaScript
// 验证关系
console.log(peppa.__proto__ === Pig.prototype); // true
我的理解总结: 实例对象通过 __proto__ 属性,指向了构造函数的原型对象。
5. 原型链:本质是“查找机制”
当我们理解了上面两个概念,原型链其实就是一个顺着 __proto__ 向上查找的机制。
当我们调用 peppa.sleep() 时,查找过程如下:
Code snippet
-
第一步(查自己): 引擎首先检查
peppa实例本身有没有sleep属性。- 结果:没有(只有 name, age, father)。
-
第二步(顺藤摸瓜): 引擎顺着
peppa.__proto__找到Pig.prototype。- 结果:找到了!
-
第三步(执行): 执行该方法。
如果还没找到呢?
如果 Pig.prototype 里也没有这个方法,引擎会继续找 Pig.prototype 的 proto(即 Object.prototype),一直找到 null 为止。这条查找的链路,就叫做原型链。
6. 总结与对比表
为了防止再次混淆,请记住这张对比表:
| 属性名 | prototype | proto |
|---|---|---|
| 持有者 | 构造函数 (Function) | 实例对象 (Object) |
| 形象比喻 | 公共仓库 / 模具 | 连接线 / 寻宝地图 |
| 核心作用 | 存放共享的方法和属性 | 指向原型对象,用于查找方法 |
最终结论:
-
构造函数负责建立公共仓库(
prototype)。 -
实例对象负责持有线索(
__proto__)。 -
原型链负责提供查找机制,确保实例能够通过线索找到仓库中的方法。
更多推荐


所有评论(0)