属性遮蔽指实例同名属性阻止访问原型同名属性,是属性查找顺序的自然结果而非覆盖;赋值自动触发遮蔽,可用hasownproperty和in判断来源,删除实例属性可恢复原型访问。

理解“属性遮蔽”关键在于明白:JavaScript 访问属性时,永远先查实例自身,查不到才沿 [[Prototype]] 往上找——这不是优先级选择,而是固定查找顺序。只要实例上有同名属性,原型上的同名属性就“被遮住”,根本不会被访问到。
遮蔽不是覆盖,是查找路径被提前终止
遮蔽(Property Shadowing)的本质是属性访问流程的自然结果,不是某种特殊操作或隐式覆盖:
- 引擎读取
obj.name时,第一步就是检查obj自身是否拥有name属性(即obj.hasOwnProperty('name')为true) - 如果存在,直接返回该值,完全不继续查原型链
- 原型上的
name依然完好无损,其他没定义name的实例仍能正常访问它
赋值操作会自动触发遮蔽
给实例设置一个与原型同名的属性,就会在实例上新建该属性,从而立即遮蔽原型版本:
OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。
-
obj.value = 42→ 即使Object.getPrototypeOf(obj).value是10,现在obj.value就是42 - 这个过程不修改原型,也不影响其他实例
- 即使原型上的属性是
writable: false,赋值仍会在实例上新建可写的同名属性并完成遮蔽
如何判断某个属性是否已被遮蔽
用两个操作符配合判断来源:
-
obj.hasOwnProperty('prop')返回true→ 属性在实例上,已遮蔽 -
'prop' in obj返回true,但hasOwnProperty为false→ 属性来自原型,尚未遮蔽 - 两者都为
false→ 属性不存在于实例和整个原型链
遮蔽后还能访问原型属性吗
可以,只需删除实例上的同名属性:
-
delete obj.prop后,再次访问obj.prop就会重新沿原型链查找 - 注意:
delete只对实例属性有效;对原型属性使用delete会影响所有实例,应避免 - 若原型属性被定义为
configurable: false,则无法删除,此时遮蔽不可逆
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










