属性隐藏是自有属性覆盖原型同名属性导致查找提前终止的现象,本质为属性遮蔽;通过object.hasown可判断是否被遮蔽,用object.getprototypeof可访问被遮蔽的原型属性。

“属性隐藏”在原型链中不是指属性被加密或删除,而是指自有属性覆盖了原型上的同名属性,导致查找过程提前终止、原型上的值不再生效。它本质是属性遮蔽(Property Shadowing),属于 JavaScript 属性查找机制的自然结果,而非 bug 或异常。
属性隐藏是怎么发生的?
当一个对象自身拥有与原型链上某处同名的属性时,引擎在查找该属性时,一旦在对象自身找到,就立即返回,不再继续向上查找。这就是遮蔽——原型上的属性“被盖住了”。
- Person.prototype.name = 'Unknown';
- const p = new Person();
- p.name = 'Alice'; // 此时 p 自身有了 name,遮蔽了原型上的 name
- console.log(p.name); // 'Alice',不会去查 Person.prototype.name
怎么判断某个属性是不是被遮蔽了?
关键看这个属性是否存在于对象自身,而不是原型上:
- Object.hasOwn(obj, key)(推荐):只检查对象自有属性,ES2022+ 标准方法
- obj.hasOwnProperty(key):老写法,但对重写了 hasOwnProperty 的对象不安全
- Object.getOwnPropertyNames(obj).includes(key):列出所有自有属性名(含不可枚举)
如果返回 true,说明该属性就在 obj 自身上,原型上的同名属性已被遮蔽。
怎么访问被遮蔽的原型属性?
不能直接用 obj.key,但可以通过原型对象显式访问:
- 先拿到原型:
const proto = Object.getPrototypeOf(obj); - 再从原型读取:
proto.key(前提是该属性在原型上且可访问) - 若不确定是否在直接原型上,可手动沿链查找(跳过自身):
let proto = Object.getPrototypeOf(obj);
while (proto !== null) {
if (Object.hasOwn(proto, key)) return proto[key];
proto = Object.getPrototypeOf(proto);
}
return undefined;
};
不可枚举属性也算“隐藏”吗?
是的,但属于另一类“隐藏”——它不参与 for...in 或 Object.keys() 等枚举操作,但仍能被正常访问(如 obj.toString)。这类属性通过 Object.defineProperty 设置了 enumerable: false。要看到它们,得用:
- Object.getOwnPropertyNames(obj):获取所有自有属性名(含不可枚举)
-
Object.getOwnPropertyDescriptors(obj):查看每个属性的完整描述符,包括
enumerable、writable等











