跳到主要内容

能不能描述一下原型链?

面试速答(30 秒版 TL;DR)

  • 原型链(prototype chain):对象通过 [[Prototype]] 串起来形成的一条链。
  • 属性查找规则:访问 obj.x 时,先找自身属性,找不到就沿 [[Prototype]] 向上找,直到 null 结束。
  • 就近原则:离对象最近的同名属性先生效(会遮蔽原型上的属性)。

心智模型:把它当“委托式查字典”

对象自己像一本小字典,原型像“上级字典”。

  • 读属性:查不到就向上委托。
  • 写属性:绝大多数情况下写到自己身上(不会“改到原型上”)。

图示:属性查找从下往上走

当你读 obj.k

  1. 先看 obj 自己有没有 k
  2. 没有就看 A.prototype 有没有 k
  3. 还没有就看 Object.prototype
  4. null 还没有就是 undefined

最小例子:遮蔽与委托

const parent = { x: 1 };
const child = Object.create(parent);

console.log(child.x); // 1 (来自原型 parent)
child.x = 2;
console.log(child.x); // 2 (写到自己身上,遮蔽了原型的 x)
console.log(parent.x); // 1 (原型未变)

常见追问

Q1:原型链的终点是什么?

nullObject.getPrototypeOf(Object.prototype) === null

Q2:inhasOwnfor...in 和原型链什么关系?

  • "k" in obj:自己有或原型链上有都算。
  • Object.hasOwn(obj, "k"):只看自身属性,不查原型链。
  • for...in:枚举对象自身加上原型链上的“可枚举”属性(因此通常要配合 hasOwn 过滤)。

Q3:instanceof 为什么本质是“查原型链”?

x instanceof Ctor 等价于判断:Ctor.prototype 是否出现在 x 的原型链上。


易错点/坑

  • Object.create(null) 创建的对象没有原型链(没有 Object.prototype),因此也没有 toString 等方法。
  • 原型链影响的不只是取值:比如 for...in 会把原型链上可枚举属性也扫出来。

速记要点(可背诵)

  • 原型链就是 [[Prototype]] 串起来的查找路径。
  • 读属性会沿链向上,写属性通常写自己并产生遮蔽。