object.hasown可精准判断属性是否属于对象自身,跳过原型链;for...in会遍历自身及原型链上所有可枚举属性,易导致深拷贝等逻辑错误;推荐优先使用object.keys等更直接方式。

用 Object.hasOwn 可以精准判断属性是否属于对象自身,跳过原型链上的继承属性,从而解决 for...in 遍历时误读原型属性的问题。
为什么 for-in 会遍历原型链属性
for...in 会枚举对象自身**可枚举**属性 + 原型链上所有**可枚举**属性。比如:
const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;
for (const key in child) {
console.log(key); // 输出 'b' 和 'a' —— 'a' 来自原型,不是 child 自身的
}
这常导致逻辑错误,比如深拷贝、序列化、表单校验时把不该处理的继承属性也纳入了。
Object.hasOwn 是更安全的替代方案
Object.hasOwn(obj, key)(ES2022 引入,是 Object.prototype.hasOwnProperty.call(obj, key) 的现代简写)只检查对象**自身**是否拥有该属性,不查原型链。
配合 for...in 使用即可过滤掉继承属性:
for (const key in child) {
if (Object.hasOwn(child, key)) {
console.log(`自身属性:${key} = ${child[key]}`); // 只输出 'b'
}
}
它比老写法更简洁、更可靠(避免了原型上重写 hasOwnProperty 的风险)。
其他更推荐的遍历自身属性的方式
如果目标明确是“只遍历自身可枚举属性”,还有更直接的选择:
-
Object.keys(obj):返回自身可枚举属性键数组,最常用、语义清晰 -
Object.getOwnPropertyNames(obj):包含不可枚举属性(如constructor) -
Object.getOwnPropertyDescriptors(obj):需要同时读取属性描述符时用
例如:
Object.keys(child).forEach(key => {
console.log(`${key}: ${child[key]}`); // 仅 'b'
});
兼容性与降级建议
Object.hasOwn 在现代浏览器和 Node.js 16.9+ 中原生支持。若需兼容旧环境(如 IE 或早期 Node.js),可用以下安全降级:
const hasOwn = Object.hasOwn || Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
之后统一用 hasOwn(obj, key) 即可,无需条件判断。
不复杂但容易忽略。











