JavaScript原型链是属性查找的默认行为,核心在于__proto__指向实例原型、prototype为函数提供原型起点、constructor指回构造函数;new操作符自动设置obj.__proto__ === Foo.prototype,引擎据此向上查找属性。

JavaScript 的原型和原型链不是“机制设计”,而是对象查找属性时的默认行为——理解它,关键在搞清 __proto__、prototype 和 constructor 三者谁指向谁、何时被自动设置。
为什么 new Foo() 创建的对象能访问 Foo.prototype 上的方法?
因为 new 操作符会自动把新对象的 __proto__ 指向 Foo.prototype。这不是赋值,是引擎内置规则:
-
function Foo() {}声明后,Foo.prototype自动创建(是个普通对象,带constructor指回Foo) -
const obj = new Foo()执行时,obj.__proto__ === Foo.prototype为true - 当读取
obj.method且obj自身无该属性时,JS 引擎顺着obj.__proto__向上找,即查到Foo.prototype.method
__proto__ 和 prototype 容易混淆的三个事实
它们名字像,但作用对象完全不同:
-
__proto__是每个实例对象(如{}、new Date())都有的内部属性,指向它的“原型对象” -
prototype是每个函数对象(包括 class)才有的属性,仅用于new实例时提供原型链起点 -
Object.prototype.__proto__是null——这是原型链终点,不是“没设置”,而是明确终止查找
用 Object.getPrototypeOf() 和 Object.setPrototypeOf() 替代直接操作 __proto__
__proto__ 是非标准遗留属性,虽被广泛支持但不推荐直接读写:
立即学习“Java免费学习笔记(深入)”;
- 查原型应统一用
Object.getPrototypeOf(obj),它等价于obj.__proto__但更规范 - 改原型必须用
Object.setPrototypeOf(obj, proto);直接赋值obj.__proto__ = x在严格模式下会静默失败 - 性能上,动态修改
__proto__会破坏 V8 等引擎的内联缓存(IC),导致后续属性访问变慢
class 语法下原型链怎么走?
ES6 class 是语法糖,底层仍靠函数和原型链工作:
-
class A {}编译后本质是function A() {},A.prototype依然存在 -
class B extends A {}中,B.prototype.__proto__ === A.prototype,同时B.__proto__ === A(静态方法继承) - 注意:类体中定义的方法会自动添加到
B.prototype,但static方法挂在B自身,不在原型链上
真正容易卡住的地方,往往不是“原型链怎么连”,而是忘记 __proto__ 是实例属性、prototype 是函数属性,或者在用 Object.create(null) 创建对象后还试图沿链找 toString ——那条链从一开始就被切断了。











