for in 循环会遍历对象自身及原型链上所有可枚举的字符串键属性;需用 hasOwnProperty 过滤或改用 Object.keys() 避免干扰。

for in 循环会遍历对象自身及其整个原型链上所有可枚举(enumerable: true)的字符串键属性,这是它最核心的行为特征,也是原型链影响枚举的直接原因。
原型链上的可枚举属性会被一并列出
只要某个属性存在于对象的任意一级原型(比如 Object.prototype、Array.prototype 或自定义构造函数的 prototype)上,且其 enumerable 为 true,for in 就会把它纳入遍历范围。
例如:
const person = { name: 'Alice', age: 28 };
Object.prototype.sayHi = function() { console.log('Hi!'); };
for (let key in person) { console.log(key); }
输出会包含 "name"、"age" 和 "sayHi" —— 最后一个是来自原型链的干扰项。
不可枚举属性天然被跳过
原型链上的属性即使存在,只要 enumerable: false,就不会出现在 for in 中。
常见例子包括:
• Object.prototype.toString、.hasOwnProperty 等原生方法(默认不可枚举)
• 用 Object.defineProperty 显式设为 enumerable: false 的自定义属性
这类属性对 for in 完全透明,不会造成干扰。
如何避免原型链干扰
只处理对象自身属性时,有两类可靠做法:
-
过滤法(兼容老环境):在循环体内用
obj.hasOwnProperty(key)判断,只保留自有属性 -
替代法(推荐现代写法):改用
Object.keys(obj)获取自有可枚举字符串键数组,再配合for of或forEach遍历,从源头避开原型链
Object.keys() 不受原型链影响,也不处理 Symbol 键;如需包含不可枚举字符串键,可用 Object.getOwnPropertyNames();如需包含 Symbol 键,可用 Object.getOwnPropertySymbols() 或 Reflect.ownKeys()。
不是所有原型属性都会被遍历到
以下情况不会导致原型链污染 for in 结果:
- 内置构造器(如
Object、Array)的原型方法默认不可枚举,不会出现 - 通过类或构造函数添加的原型方法若未显式设置
enumerable: true,也不会出现 - 对象直接继承自
null(如Object.create(null)),则没有原型链,for in只遍历自身
真正引发问题的,往往是开发者无意中给 Object.prototype 添加了可枚举属性,或者使用了某些老旧库做了全局原型增强。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











