文章目录

JavaScript 原型链:__proto__ 与 prototype 的关系

发布于 2026-04-08 07:26:59 · 浏览 6 次 · 评论 0 条

JavaScript 原型链:__proto__prototype 的关系

理解 JavaScript 中的原型链,核心在于搞清楚两个长得很像但作用完全不同的属性:prototype__proto__。这不仅是面试的高频考点,更是理解 JS 对象继承机制的基石。

我们将通过具体的代码演示和内存逻辑,拆解这两者的关系。


1. 核心概念:谁是蓝图,谁是线索

在深入代码之前,先建立两个基本认知:

  • prototype (原型对象):它是函数特有的一块“预留仓库”。你在这个仓库里存放的东西,所有由该函数制造出来的对象都可以共用。
  • __proto__ (原型指针):它是对象身上自带的一根“线索”。这根线索指向制造它的那个函数的“预留仓库”。

2. 实操演示:建立连接

打开浏览器控制台,输入以下代码来验证两者如何关联。

第一步:定义构造函数

定义一个名为 Dog 的构造函数。此时,JS 引擎会自动给这个函数附带一个 prototype 属性,它是一个空对象。

function Dog(name) {
    this.name = name;
}

第二步:添加共享方法

访问 Dog.prototype,并添加一个 bark 方法。相当于往“仓库”里放了一个工具。

Dog.prototype.bark = function() {
    console.log("汪汪");
};

第三步:创建实例

使用 new 关键字创建一个实例对象 myDog

const myDog = new Dog("旺财");

第四步:验证链接公式

输入以下等式进行验证。这是理解原型链最核心的数学关系:

$$ 实例.\_\_proto\_\_ === 构造函数.prototype $$

在控制台输入

console.log(myDog.__proto__ === Dog.prototype);

观察输出结果,返回 true。这证明了 myDog 身上的 __proto__ 线索,精准地指向了 Dogprototype 仓库。


3. 可视化结构:对象与原型的地图

为了更直观地理解这种指向关系,我们可以通过流程图来看清内存中的结构。

graph LR subgraph "构造函数 Function" A["Dog (构造函数)"] end subgraph "原型仓库 Prototype" B["Dog.prototype\n{ bark: ... }"] end subgraph "实例对象 Instance" C["myDog\n{ name: '旺财' }"] end A -- "prototype 属性指向" --> B C -- "__proto__ 指针指向" --> B

从图中可以看出:

  1. Dog 函数拥有 prototype 属性,指向原型对象。
  2. myDog 实例拥有 __proto__ 属性,也指向那个原型对象。
  3. 两者最终指向了同一个内存地址。

4. 属性查找机制:顺着线索找工具

为什么我们在 myDog 身上没写 bark 方法,却能调用它?执行以下代码:

myDog.bark();

此时 JavaScript 引擎会执行以下查找步骤:

  1. 搜索 myDog 自身:有没有 bark?没有。
  2. 跟随 myDog.__proto__ 线索:找到了 Dog.prototype
  3. 搜索 Dog.prototype:有没有 bark?有,执行它。
  4. 如果 Dog.prototype 还没有,引擎会继续顺着 Dog.prototype.__proto__ 往上找,直到找到 Object.prototype 或终点 null

这就是“原型链”名字的由来——由 __proto__ 串联起来的一条查找链条。


5. 终极链条:直到尽头

所有的原型链条最终都会汇合到一个终点。输入以下代码查看链条的顶端:

console.log(myDog.__proto__ === Dog.prototype);        // true
console.log(Dog.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null);       // true

这说明:

  • Dog.prototype 也是一个对象,它是 Object 的实例。
  • Object.prototype 是原型链的顶端,它的 __proto__ 指向 null,表示链条结束。

6. 对比总结表

为了防止混淆,请牢记下表的区别:

属性名 归属对象 作用 读写性
prototype 函数 定义实例的共享属性和方法(仓库) 可读写
__proto__ 对象 指向构造函数的 prototype(线索) 可读写(但不推荐)
constructor prototype 对象 指回原来的构造函数 可读写

记住这个最实用的技巧:当你想知道一个对象能用什么方法时,查找它的 __proto__(或 Object.getPrototypeOf(obj));当你想给一类对象共享方法时,修改构造函数的 prototype

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文