JS原型链属性遮蔽疑问:为何a.val++会创建自身属性而非修改原型属性?
原型委托与属性遮蔽的核心逻辑解析
你遇到的问题核心是没拆解清楚a.val++的执行过程——它不是单纯的属性访问,而是读操作+写操作的组合,这正好触发了《YDKJS》中提到的属性遮蔽规则,和委托访问的描述并不矛盾。
拆解a.val++的执行步骤
- 读阶段(委托访问):JS引擎先在对象
a自身查找val属性,找不到时会沿着原型链委托访问Foo.prototype.val,拿到值1——这一步完全符合书中“属性通过委托访问”的描述。 - 写阶段(触发遮蔽):将读取到的
1自增为2后,JS需要把新值存储。此时因为Foo.prototype.val是普通可写属性(默认writable: true),按照书中规则,引擎不会修改原型上的属性,而是直接在a自身创建一个新的val属性并赋值2,形成属性遮蔽。
验证规则的反向案例
如果把原型上的val设置为只读,写操作就无法触发遮蔽,会直接沿用原型的属性:
// 把原型的val改为只读 Object.defineProperty(Foo.prototype, 'val', { value: 1, writable: false }); a.val++; // 严格模式下会抛出错误,非严格模式无效果 console.log(a.val); // 输出1,依然委托访问原型的val console.log(Foo.prototype.val); // 输出1
关键区分:读操作 vs 写操作
- 单纯读操作(如
console.log(a.val)):若自身无对应属性,会一直沿原型链委托访问,不会创建新属性。 - 写操作(包括赋值、自增/自减等):仅当原型上的属性是只读或**访问器属性(getter/setter)**时,才会直接操作原型属性;否则会在当前对象创建遮蔽属性。
内容的提问来源于stack exchange,提问作者Sadiq
相关产品推荐
相关产品推荐

