能不能描述一下原型链?
面试速答(30 秒版 TL;DR)
- 原型链(prototype chain):对象通过
[[Prototype]]串起来形成的一条链。 - 属性查找规则:访问
obj.x时,先找自身属性,找不到就沿[[Prototype]]向上找,直到null结束。 - 就近原则:离对象最近的同名属性先生效(会遮蔽原型上的属性)。
心智模型:把它当“委托式查字典”
对象自己像一本小字典,原型像“上级字典”。
- 读属性:查不到就向上委托。
- 写属性:绝大多数情况下写到自己身上(不会“改到原型上”)。
图示:属性查找从下往上走
当你读 obj.k:
- 先看
obj自己有没有k - 没有就看
A.prototype有没有k - 还没有就看
Object.prototype - 到
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:原型链的终点是什么?
null。Object.getPrototypeOf(Object.prototype) === null。
Q2:in、hasOwn、for...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]]串起来的查找路径。 - 读属性会沿链向上,写属性通常写自己并产生遮蔽。