for...in遍历对象自身及原型链上可枚举属性,需用object.prototype.hasownproperty.call(obj, key)过滤继承属性;推荐改用object.keys()配合for...of,天然只返回自身可枚举键名。

在 for...in 循环中只遍历对象自身的可枚举属性,关键在于过滤掉继承自原型链的属性——最直接可靠的方式是使用 hasOwnProperty() 方法做判断。
用 hasOwnProperty() 筛选自身属性
for...in 会遍历对象自身及其原型链上所有**可枚举**的属性。要排除原型上的,只需在循环体内检查该属性是否属于对象自身:
- 调用
obj.hasOwnProperty(prop),返回true表示prop是obj自身的自有属性(不是从原型继承的) - 注意:必须用
Object.prototype.hasOwnProperty.call(obj, prop)更稳妥,避免对象自身重写了hasOwnProperty方法(比如obj = { hasOwnProperty: true })
示例:
const obj = { a: 1 };obj.__proto__.b = 2; // b 在原型上
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(key); // 只输出 'a'
}
}
改用 Object.keys() + for...of(推荐)
Object.keys(obj) 返回的是对象**自身可枚举属性名**组成的数组,天然不包含原型属性,语义更清晰、代码更简洁:
- 它只返回自有(own)、可枚举(enumerable)属性的键名,完全绕过原型链干扰
- 配合
for...of或数组方法(如forEach)使用,可读性和健壮性更高
示例:
const obj = { a: 1 };obj.__proto__.b = 2;
for (const key of Object.keys(obj)) {
console.log(key); // 只输出 'a'
}
设置属性时注意 enumerable 特性
如果确实需要往原型上添加属性但又不希望被 for...in 遍历到,可将属性设为不可枚举:
- 用
Object.defineProperty()显式定义,并把enumerable: false - 这样即使属性在原型上,
for...in和Object.keys()都不会访问到它
示例:
const proto = {};Object.defineProperty(proto, 'hidden', {
value: 'secret',
enumerable: false
});
const obj = Object.create(proto);
obj.a = 1;
for (let k in obj) console.log(k); // 只输出 'a'
避免污染内置原型(预防性原则)
不要直接修改 Array.prototype、Object.prototype 等内置原型——这类操作不仅影响全局,还会让所有实例在 for...in 中意外暴露新增属性:
- 例如
Array.prototype.myMethod = function(){}后,每个数组在for...in中都会遍历到'myMethod' - 如需扩展功能,优先用工具函数、ES6 类或 `Symbol` 方法,或确保设为
enumerable: false
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











