原型链的核心是构造函数、实例对象、原型对象的三角关系:person.prototype指向原型,p.__proto__等于person.prototype,person.prototype.constructor指回person;查找属性时自底向上委托,终点为null。

直接抓住三条主线:构造函数、实例对象、原型对象之间的关系,再理清查找路径和终点,原型链就清晰了。
搞懂三角关系:prototype、__proto__、constructor
这是原型链的地基,三者必须能互相验证:
-
构造函数(如
function Person(){})有prototype属性,指向它的原型对象; -
实例对象(如
const p = new Person())有__proto__属性,值等于Person.prototype; -
原型对象(
Person.prototype)有constructor属性,指回Person函数本身。
用这三行代码就能闭环验证:
console.log(p.__proto__ === Person.prototype);console.log(Person.prototype.constructor === Person);
console.log(p.constructor === Person);
看清链式结构:从实例一直追到 null
原型对象本身也是对象,它也有自己的 __proto__,这就串成了链:
- 实例
p.__proto__→Person.prototype; -
Person.prototype.__proto__→Object.prototype(所有普通对象的顶层原型); -
Object.prototype.__proto__→null(链路终止点,不可再往上)。
执行 console.log(p.__proto__.__proto__.__proto__),结果就是 null,这就是最简明的链路终点证明。
掌握属性查找规则:自底向上,找不到才停
JS 访问属性时不是“复制”,而是“委托查找”:
- 先查对象自身(
p.name); - 没找到,就去
p.__proto__(即Person.prototype)上找; - 还没找到,继续去
Person.prototype.__proto__(即Object.prototype)上找; - 直到
null还没找到,返回undefined。
比如 p.toString() 不在 p 或 Person.prototype 上,但能在 Object.prototype 找到——这就是原型链生效的过程。
警惕常见误区和风险点
理解原理后,要避开实际开发中的坑:
- 不要随意修改内置对象原型(如
Date.prototype.format = ...),容易引发全局污染和遍历异常; -
for...in会枚举原型链上的可枚举属性,判断自有属性要用hasOwnProperty(); -
instanceof的本质是检测右操作符的prototype是否出现在左操作符的原型链上; - 箭头函数没有
prototype,不能当构造函数用。











