JavaScript中for...in与for...of循环差异及混用生效原因探究
JavaScript中for...in与for...of的底层差异及混用问题解析
核心底层逻辑差异
- for...in循环:本质是遍历对象的可枚举属性名。数组在JS里属于特殊对象,它的可枚举属性就是字符串类型的索引(比如
"0"、"1"),遍历过程中拿到的是这些字符串形式的索引值。 - for...of循环:遍历的是可迭代对象的迭代器返回值。数组的内置迭代器会直接返回每个元素的实际值,所以能直接拿到数组里的
1、2、3这类元素。
你的两种场景分析
1. 输出奇数时“生效”的巧合
你写的代码:
let numbers = [1,2,3,4,5,6,7,8,9,10] function displayOddNumbers() { for (num in numbers) { num % 2 != 0 ? console.log(num) : console.log(); }; };
这里num是数组的索引(字符串类型,比如"1"),在执行num % 2时,JS会自动把字符串转成数字。你输出的是奇数索引(1、3、5、7、9),而这些索引的数值刚好和数组里的奇数元素(1、3、5、7、9)完全一致,所以你误以为代码正确——但本质是输出了索引,只是数值巧合匹配了目标元素。如果数组元素不是从1开始的连续整数,这个代码会直接出错。
2. 输出偶数时失效与修正的原因
最初的失效代码:
function displayEvenNumbers() { for (num in numbers) { num % 2 == 0 ? console.log(num) : console.log(); }; };
你想输出偶数元素,但这里输出的是偶数索引(0、2、4、6、8),这些索引对应的数组元素是1、3、5、7、9(奇数),完全不是你要的结果,所以看起来“失效”。
修改后的代码:
function displayEvenNumbers() { for (num in numbers) { num % 2 != 0 ? console.log(numbers[num]) : console.log(); }; };
这里你通过numbers[num]取到了奇数索引对应的数组元素(索引1→2、索引3→4...),这些元素刚好是你要的偶数,所以代码“生效”。但这个逻辑是绕了弯路的:你通过判断索引的奇偶性,反向拿到了目标元素,本质还是利用了数组索引和元素值的对应关系,不是正确的遍历方式。
总结
遍历数组优先用for...of、普通for循环或forEach,for...in是为遍历普通对象的属性设计的,用来遍历数组会因为以下问题出错:
- 拿到的是字符串类型的索引,容易在隐式转换中产生意外
- 可能遍历到数组原型上的自定义可枚举属性
- 遍历顺序不保证严格按数组索引顺序
内容的提问来源于stack exchange,提问作者user53
相关产品推荐
相关产品推荐

