JavaScript原型链是对象属性查找的底层机制:从实例__proto__逐级向上追溯至null;class是prototype语法糖;new和Object.create()均设置__proto__但行为不同;常见陷阱包括污染原生原型、误用constructor及混淆__proto__与prototype。

JavaScript 中的 prototype 和原型链不是“进阶知识”,而是对象行为的底层执行机制——不理解它,就无法真正看懂 instanceof 的结果、this 的指向、甚至 class 里 super() 到底在调什么。
原型链是怎么跑起来的:从 obj.method() 开始查
每次访问一个对象上不存在的属性或方法,JS 引擎会沿着 __proto__(即内部 [[Prototype]])一级级向上找,直到找到或抵达 null。这个查找路径就是原型链。
关键点:
-
__proto__是实例对象的属性,指向其构造函数的prototype -
Function.prototype是所有函数的原型,而Object.prototype是几乎所有对象的最终原型 -
Object.prototype.__proto__ === null,这是链的终点
const arr = [1, 2]; console.log(arr.__proto__ === Array.prototype); // true console.log(Array.prototype.__proto__ === Object.prototype); // true console.log(Object.prototype.__proto__); // null
class 语法只是语法糖:背后全是 prototype 操作
ES6 的 class 并没有引入新的继承模型,它只是把基于 prototype 的操作封装得更像 Java/C++。编译后,所有方法都挂载在构造函数的 prototype 上。
立即学习“Java免费学习笔记(深入)”;
容易误解的地方:
-
class A { method() {} }→ 实际等价于A.prototype.method = function() {} -
static method()→ 挂在A.method上,不进原型链,实例不可访问 -
extends B→ 底层是A.__proto__ = B(构造函数继承),且A.prototype.__proto__ = B.prototype(实例原型继承)
class Parent {
constructor(name) { this.name = name; }
say() { return `Hi ${this.name}`; }
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
// 等效于:
// Child.prototype.__proto__ = Parent.prototype;
为什么 new 和 Object.create() 行为不同但本质一致
两者都创建新对象并设置其 __proto__,但触发时机和默认行为不同:
-
new C():创建空对象 → 设置__proto__为C.prototype→ 执行C.call(新对象, ...) -
Object.create(proto):直接以proto为__proto__创建对象,不调用任何构造函数 - 若想模拟
new,需手动绑定this并调用构造函数,否则不会初始化实例属性
function Person(name) {
this.name = name;
}
const p1 = new Person('Alice'); // name 在实例上
const p2 = Object.create(Person.prototype);
p2.constructor.call(p2, 'Bob'); // 必须手动调用,否则 p2.name === undefined
常见陷阱:修改原生原型、误用 constructor、混淆 __proto__ 与 prototype
最常踩坑的三个点:
- 给
Array.prototype加方法看似方便,但会影响所有数组的for...in遍历(除非用Object.defineProperty设为不可枚举) -
obj.constructor不可靠——它只是obj.__proto__.constructor,一旦原型被替换(如A.prototype = {}),constructor就断了 -
obj.__proto__是实例属性,Obj.prototype是函数属性;写错位置会导致继承链断裂,比如把方法加到Obj本身而非Obj.prototype
真正要检查原型关系,用 Object.getPrototypeOf(obj) === SomeClass.prototype 或 obj instanceof SomeClass,别依赖 constructor。










