遮蔽是对象自身赋值同名属性覆盖原型成员的行为,不修改原型仅改变查找路径;可通过 delete 恢复原型访问,引用类型需赋新对象才触发遮蔽。

当给对象直接赋值一个与原型上同名的属性或方法时,JavaScript 会在这个对象自身创建该属性,从而“遮蔽”(shadow)原型链上的同名成员——不是删除或修改原型,而是让查找过程在对象自身就停止,不再继续向上。
遮蔽只发生在赋值时,不依赖定义方式
只要对对象执行 obj.method = ... 或 obj.prop = ...,无论右侧是函数、字符串还是其他值,都会在 obj 自身添加该键。之后访问 obj.method 就永远取自身值,原型上的同名方法完全被跳过。
- 即使原型方法是通过
Constructor.prototype.method = function(){}定义的,实例赋值后也立即遮蔽 - 箭头函数、普通函数、甚至
null或undefined都能触发遮蔽 - 遮蔽是对象级别的,不影响其他实例(除非它们也做了同样赋值)
遮蔽后仍可显式调用原型方法
遮蔽只是改变了默认查找路径,并不切断原型链接。你仍可通过以下方式访问被遮蔽的原型方法:
Object.getPrototypeOf(obj).methodName.call(obj, ...args)-
obj.__proto__.methodName.call(obj, ...args)(不推荐,__proto__非标准) - 若知道构造函数:
MyClass.prototype.methodName.call(obj, ...args)
例如:一个 Person 实例 p 遮蔽了 toString,仍可用 Person.prototype.toString.call(p) 获取原始行为。
删除自身属性可恢复原型访问
使用 delete obj.prop 移除被遮蔽的自有属性后,下一次访问该属性就会重新沿原型链查找,自然回到原型上的定义。
-
delete p.name后再读p.name,若Person.prototype.name存在,就会取它 - 注意:
delete对继承属性无效(返回false),只作用于对象自身的可配置属性 - 用
hasOwnProperty('prop')可快速判断当前是否处于遮蔽状态
常见误操作:引用类型属性遮蔽易引发意外共享
如果原型上挂的是对象、数组等引用类型(如 Person.prototype.config = { theme: 'light' }),多个实例未遮蔽时会共用同一份数据。一旦某个实例执行 p.config.theme = 'dark',其实只是修改了共享对象的属性——这不是遮蔽;要真正遮蔽,必须赋新对象:p.config = { theme: 'dark' }。
- 前者(改内部属性):所有实例看到
config.theme都变暗 - 后者(赋新对象):仅
p自身拥有独立config,实现真正遮蔽 - 所以初始化引用类型应放在构造函数内(
this.config = {...}),避免原型污染风险
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











