for...in会遍历原型链上可枚举属性、不保证顺序、忽略Symbol键、无法遍历Map/Set等内置对象;应配合hasOwnProperty过滤或改用Object.keys()、Object.entries()、Reflect.ownKeys()等更安全的方法。

for...in 会遍历原型链上的可枚举属性
这是最常被忽略的陷阱。for...in 不只遍历对象自身的属性,还会顺着 __proto__ 向上遍历所有可枚举的继承属性。比如给 Object.prototype 添加了方法(不推荐但现实中存在),它就会出现在每个对象的 for...in 循环里。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 始终用
hasOwnProperty()过滤:if (obj.hasOwnProperty(key)) { /* 处理 */ } - 更现代的替代是
Object.keys(obj)+for...of,它只返回自身可枚举属性键名 - 注意:
hasOwnProperty本身可能被覆盖,安全写法是Object.prototype.hasOwnProperty.call(obj, key)
for...in 遍历顺序不保证(尤其数字键)
ECMAScript 规范不保证 for...in 的遍历顺序。虽然现代引擎对字符串键基本按定义顺序,但对纯数字键(如 "1", "2", "10")会按数值大小排序,导致 "10" 出现在 "2" 前面——这和数组索引直觉相悖。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 若依赖顺序,改用
Object.keys(obj).sort().forEach(...)显式控制 - 或直接用
Object.entries(obj)获取[key, value]数组,再用for...of或map() - 数字索引为主的结构,优先考虑
Array而非普通对象
for...in 不能可靠遍历 Symbol 属性
for...in 只遍历字符串键名,完全忽略 Symbol 类型的键。哪怕该 Symbol 属性是可枚举的,也不会出现。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 要访问 Symbol 属性,必须用
Object.getOwnPropertySymbols(obj)单独获取 - 想同时拿到字符串键和 Symbol 键,需组合:
[...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)] - 注意:
Reflect.ownKeys(obj)是更简洁的替代,它返回所有自有键(含字符串 + Symbol)
Map/Set 等内置集合不能用 for...in 遍历
for...in 对 Map、Set、ArrayBuffer 等内置对象无效——它们没有可枚举的字符串键属性,循环体根本不会执行。
实操建议:
立即学习“Java免费学习笔记(深入)”;
-
Map用for...of+entries()/keys()/values() -
Set直接for...of set或set.forEach() -
Array优先用for...of、forEach()、map(),避免for...in(它会把数组当普通对象,可能遍历到意外的属性)
真正容易出问题的,是忘记 hasOwnProperty 检查,以及误以为 for...in 能像 for...of 那样通用处理各种数据结构。











