原型链是JavaScript运行时属性查找机制,通过__proto__向上委托查找直至null;instanceof依赖此链判断,断链则失效;class只是语法糖,底层仍基于原型链。

不理解原型链,JavaScript 的很多行为就只能靠死记硬背,比如为什么 arr.toString() 能用、obj.constructor 有时是 Object 有时不是、instanceof 到底在查什么——这些都不是语法糖,而是原型链在背后实时运作的结果。
什么是原型链:它不是设计,而是运行时查找机制
JavaScript 没有“类继承”这种编译期结构,只有对象间动态委托的属性查找路径。每次访问一个对象上不存在的属性(比如 obj.xxx),引擎会顺着 obj.__proto__ 往上找,直到找到或到达 null。这条链就是原型链。
关键点:
-
__proto__是每个对象都有的内部引用(已不推荐直接使用,但理解它最直观) -
prototype是函数才有的属性,只在用new创建实例时参与链的构建 -
Object.getPrototypeOf(obj)和Object.setPrototypeOf()才是标准操作方式 - 所有函数默认有
prototype,其constructor指回该函数;但普通对象没有prototype属性
为什么 instanceof 会失效?原型链被意外切断
instanceof 的本质是检查右操作数的 prototype 是否出现在左操作数的原型链中。一旦链断了,判断就错。
立即学习“Java免费学习笔记(深入)”;
常见断链场景:
- 用字面量创建对象后手动赋值
obj.__proto__ = null - 用
Object.create(null)创建的对象,原型为null,不继承任何方法(包括toString) - 跨 iframe 时,不同上下文的
Array构造函数不同,arr instanceof Array返回false,得用Array.isArray(arr) - 用
Object.assign({}, obj)浅拷贝时,目标对象的原型是Object.prototype,丢失原对象的自定义原型链
ES6 class 也没绕过原型链,只是语法糖
class 写法看着像 Java,但底层仍是基于原型。以下两段代码行为完全一致:
class Person {
constructor(name) { this.name = name; }
say() { return `Hi, ${this.name}`; }
}
等价于:
function Person(name) { this.name = name; }
Person.prototype.say = function() { return `Hi, ${this.name}`; };
所以:
-
class A extends B实际设置的是A.prototype.__proto__ === B.prototype -
super()在构造函数里,本质是调用B.call(this, ...),不是“调父类构造器”,而是手动绑定父构造逻辑 - 静态方法(
static)挂载在Class函数本身上,不在原型链上,所以不能被实例继承
原型链不是历史包袱,它是 JavaScript 动态性、轻量级对象模型的核心支撑。真正难的不是记住规则,而是在写 Object.create、封装 new、调试 this 绑定、或者排查 hasOwnProperty 返回 false 时,能立刻意识到该去哪一层原型上看——而不是翻文档猜。











