要过滤原型链属性只遍历自身可枚举属性,应使用 Object.prototype.hasOwnProperty.call(obj, key) 判断,或改用 Object.keys(obj) 配合 for-of;二者均不处理不可枚举属性和 Symbol 键。

要过滤掉原型链上继承来的属性,只遍历对象自身的可枚举属性,关键在于使用 hasOwnProperty 方法做判断。
用 hasOwnProperty 筛选自身属性
for-in 会遍历对象自身及其原型链上所有可枚举属性。要排除继承属性,需在循环体内检查当前属性是否属于对象自身:
- 每个对象都继承自
Object.prototype,拥有hasOwnProperty方法 - 它返回布尔值:
true表示该属性直接定义在对象上(非继承) - 注意:不能用
obj.hasOwnProperty(prop)直接调用,以防对象自身重写了该方法;更稳妥写法是Object.prototype.hasOwnProperty.call(obj, prop)
推荐写法(安全且清晰)
以下代码能可靠过滤原型链属性:
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(key, obj[key]);
}
}这样即使 obj 自身有同名的 hasOwnProperty 属性或被污染,也不会影响判断逻辑。
立即学习“Java免费学习笔记(深入)”;
替代方案:用 Object.keys() + for-of
如果不需要兼容非常老的环境(如 IE9 以下),更简洁的方式是避开 for-in:
-
Object.keys(obj)只返回对象自身可枚举属性的键数组 - 配合
for-of或forEach遍历,天然不涉及原型链 - 例如:
for (const key of Object.keys(obj)) { /* 处理 obj[key] */ }
注意不可枚举属性和 Symbol 键
for-in 和 Object.keys() 都只处理**可枚举的字符串键**:
- 不可枚举属性(如通过
Object.defineProperty设置enumerable: false)不会出现 - Symbol 类型的键也完全不会被
for-in或Object.keys()捕获,需用Object.getOwnPropertySymbols()单独获取


















