【js篇】JavaScript 原型链指向全解析

38 阅读3分钟

在 JavaScript 中,原型链的指向关系看似错综复杂,实则遵循一套清晰的规则。理解这些指向,是掌握继承机制、调试对象结构、深入学习框架源码的基础。

本文将结合你提供的代码片段,逐行解析每个表达式的含义,并通过图示+文字的方式,帮你彻底理清原型链中的关键指向。


一、实验环境准备

我们先定义一个简单的构造函数和实例:

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

const p = new Person('Alice');

现在,我们来逐一分析你列出的每一个表达式。


二、逐行解析原型链指向

p.__proto__Person.prototype

p.__proto__ === Person.prototype // true
  • pPerson 的实例;
  • 实例的 __proto__ 指向其构造函数的 prototype
  • 这是原型链的第一级连接

📌 结论:实例 → 构造函数的 prototype


Person.prototype.__proto__Object.prototype

Person.prototype.__proto__ === Object.prototype // true
  • Person.prototype 本身是一个普通对象(由 Object 构造);
  • 所有普通对象的原型都指向 Object.prototype
  • 这是原型链的第二级连接

📌 结论:构造函数的 prototype → Object.prototype


p.__proto__.__proto__Object.prototype

p.__proto__.__proto__ === Object.prototype // true
  • 第一级:p.__proto__Person.prototype
  • 第二级:Person.prototype.__proto__Object.prototype

这正是原型链向上查找的过程。

📌 结论:实例 → 构造函数原型 → Object.prototype


p.__proto__.constructor.prototype.__proto__Object.prototype

我们拆解这个复杂表达式:

  1. p.__proto__Person.prototype
  2. Person.prototype.constructorPerson(默认情况下)
  3. Person.prototype → 构造函数的原型对象
  4. Person.prototype.__proto__Object.prototype

所以:

p.__proto__.constructor.prototype.__proto__ === Object.prototype // true

📌 本质:绕了一圈又回到了 Person.prototype.__proto__


Person.prototype.constructor.prototype.__proto__Object.prototype

同理:

  1. Person.prototype.constructorPerson
  2. Person.prototype → 原型对象
  3. Person.prototype.__proto__Object.prototype

结果相同。

📌 说明:无论从哪个路径出发,只要最终走到 Person.prototype.__proto__,都会指向 Object.prototype


p.__proto__.constructorPerson

p.__proto__.constructor === Person // true
  • p.__proto__Person.prototype
  • Person.prototype.constructor 默认指向 Person
  • 这是构造函数与原型之间的双向绑定

📌 重要用途:通过实例可以反向找到其构造函数


Person.prototype.constructorPerson

Person.prototype.constructor === Person // true
  • 这是 JavaScript 为每个构造函数自动设置的属性;
  • 保证了“原型 → 构造函数”的可追溯性。

⚠️ 注意:如果重写了 Person.prototype 而未手动设置 constructor,这个关系就会断裂!


三、原型链示意图

       p (实例)
        ↓ __proto__
Person.prototypeconstructor: Person
        ↓ __proto__
  Object.prototype
        ↓ __proto__
        null
  • 查找属性时:pPerson.prototypeObject.prototypenull
  • 反向追溯构造函数:p.__proto__.constructorPerson

四、验证与调试技巧

你可以使用以下方法在浏览器控制台中验证原型链:

// 查看实例的原型
Object.getPrototypeOf(p) === Person.prototype; // true

// 查看原型的原型
Object.getPrototypeOf(Person.prototype) === Object.prototype; // true

// 查看构造函数
p.constructor === Person; // true(前提是 constructor 未被破坏)

// 完整原型链
console.log(p);
// 展开后可看到:__proto__: Person → __proto__: Object → __proto__: null

五、常见陷阱提醒

表达式是否安全说明
p.__proto__⚠️ 不推荐应使用 Object.getPrototypeOf(p)
Person.prototype.__proto__⚠️ 不推荐应使用 Object.getPrototypeOf(Person.prototype)
p.constructor✅ 但需注意若原型被重写且未修复 constructor,则可能指向 Object

六、总结:核心指向关系一览表

表达式指向目标说明
p.__proto__Person.prototype实例的原型
Person.prototype.__proto__Object.prototype原型对象的原型
p.__proto__.__proto__Object.prototype原型链第二级
p.__proto__.constructorPerson从原型反向找构造函数
Person.prototype.constructorPerson构造函数与原型的绑定
*.constructor.prototype.__proto__Object.prototype最终都归于 Object

💡 结语

“原型链不是迷宫,而是有向图;只要掌握几个关键节点,就能自由穿梭。”

理解 p.__proto__constructorprototype 三者之间的关系,是成为高级前端开发者的重要一步。记住:

  • 实例通过 __proto__ 指向原型;
  • 原型通过 constructor 指回构造函数;
  • 构造函数再通过 prototype 指向原型;
  • 原型链最终指向 Object.prototype 并以 null 结束。

把这些关系画在纸上,多练习几次,你就能真正“看见”JavaScript 的原型世界。