属性遮蔽不是覆盖原型,而是属性查找时的优先级短路:先查自身,命中即止,原型属性仍完好;赋值默认新建自有属性,delete仅移除自身属性,之后访问自然回退到原型。

属性屏蔽不是“覆盖原型”,而是访问时的查找优先级短路:只要对象自身有同名属性,引擎就不再往上找原型链。
屏蔽的本质是查找顺序,不是修改原型
JavaScript 访问属性始终按固定路径执行:
- 先查对象自身(own property)
- 没找到才沿 [[Prototype]] 向上逐层查找
- 一旦在某一层命中,立即返回,不继续向上
所谓“屏蔽”,只是因为查找在第一步就结束了。原型上的属性依然完好无损,只是被跳过了。
赋值和删除行为印证屏蔽逻辑
对 obj.x = val 的处理完全取决于 obj 自身是否已有 x:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 若
obj自身没有x,且原型链上存在可写x,赋值仍会把x新增到obj自身(触发屏蔽) - 若
obj自身已有x,赋值只改它,原型不受影响 -
delete obj.x只删自身属性;删完再读obj.x,就会自然落到原型上,显出“继承恢复”效果
方法与访问器的屏蔽差异需特别注意
普通方法和数据属性屏蔽规则一致,但访问器(getter/setter)例外:
- 若原型上定义了
get x(),直接写obj.x = 123不会新建自有属性,而可能触发原型的 setter - 要真正屏蔽访问器,必须在自身用
Object.defineProperty显式定义同名 get/set - 否则看似“赋值”,实际是委托给原型处理,不是屏蔽
如何准确判断一个属性是否被屏蔽?
别用 in 或 obj.x === undefined,它们无法区分“未定义”和“值为 undefined”:
- ✅ 正确方式:
obj.hasOwnProperty('x')—— 返回true表示自有属性,即已屏蔽 - ✅ 辅助验证:
obj.__proto__.hasOwnProperty('x')看原型是否原本就有 - ❌
'x' in obj会返回true即使x来自原型,无法识别屏蔽

















