属性遮蔽效应指子对象添加同名自有属性后优先读取自身值而不再查找原型;写入时默认在当前对象创建/修改属性导致遮蔽,读取时通过hasownproperty可检测是否被遮蔽。

在 JavaScript 中,原型链继承时的属性遮蔽效应(Property Shadowing)是指子对象自身添加同名属性后,会“遮蔽”原型链上同名的属性——访问该属性时优先读取自身属性,不再向上查找原型。
遮蔽效应如何发生
当一个对象拥有与原型链上某个属性同名的自有属性时,JavaScript 的属性访问机制会停止向上查找,直接返回当前对象的值。这本质是原型链查找规则决定的:从自身开始,逐级向上,找到第一个匹配即停止。
例如:
const parent = { name: 'Parent', age: 30 };const child = Object.create(parent);
child.name = 'Child'; // 在 child 自身添加 name 属性
console.log(child.name); // 'Child'(遮蔽了 parent.name)
console.log(child.age); // 30(未遮蔽,沿原型链找到 parent.age)
遮蔽只影响读取,不影响写入逻辑
给对象属性赋值时,如果该属性可写且存在(包括在原型上),默认行为是在**当前对象上创建或修改自有属性**,而不是修改原型上的属性。这就是遮蔽发生的典型时机。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 若 child 没有自有 name,
child.name = 'New'会直接在 child 上新建 name,遮蔽 parent.name - 若想真正修改原型上的属性,需显式访问:
Object.getPrototypeOf(child).name = 'New' - 使用
Object.defineProperty并设置writable: false或configurable: false可阻止遮蔽(但会抛错或静默失败,取决于严格模式)
构造函数继承中遮蔽的常见陷阱
用 function Child() { this.name = 'Child'; } 并设置 Child.prototype = Object.create(Parent.prototype) 时,实例化后 new Child() 的自有 name 会自动遮蔽原型或父类构造器中可能设置的同名属性。
- 父类在构造器中初始化
this.name,子类也在构造器中赋值this.name→ 子类值生效,父类值被覆盖(非遮蔽,是重写) - 若父类仅在原型上定义
name(如Parent.prototype.name = 'P'),而子类实例在运行时执行inst.name = 'C'→ 发生遮蔽 - 检查是否被遮蔽可用
inst.hasOwnProperty('name')返回true表示已遮蔽
主动利用遮蔽实现多态行为
遮蔽不是 bug,而是实现“实例级定制”的自然方式。比如多个子实例共享同一原型方法,但各自用自有属性覆盖配置项:
const Button = { type: 'button', click() { console.log(this.type); } };const submitBtn = Object.create(Button);
submitBtn.type = 'submit'; // 遮蔽原型 type
submitBtn.click(); // 'submit'
这种模式轻量、无需 class,适合配置驱动的对象系统。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










