必须用for循环:需提前跳出(如break/return)、异步串行执行、遍历类数组或性能敏感场景;foreach仅适合完整遍历且无需中断的副作用操作。

选哪个,关键看你要干什么:只遍历执行操作,用 forEach;要生成新数组,用 map 或 filter;需要中途跳出、性能敏感或操作非数组(如对象、DOM 节点),就该用 for 循环。
什么时候必须用 for 循环
for 循环是唯一能自然中断的遍历方式,适合有明确退出条件的场景:
- 找到目标后立刻 break(比如搜索第一个偶数)
- 遇到异常需 continue 跳过当前项(比如跳过空值或非法数据)
- 处理超大数组(10 万以上),对执行速度有硬性要求
- 遍历类数组对象(
arguments、NodeList)、字符串或对象键名(需配合Object.keys())
forEach 适合做什么
它语义清晰,专为“对每个元素做点事”而生,但不返回结果:
- 批量打日志、发请求、更新 DOM、触发事件等副作用操作
- 代码可读性优先,且不需要中途停止(return 不会跳出循环)
- 不修改原数组,也不依赖返回值——它的返回值永远是
undefined
map 和 filter 的核心分工
它们都返回新数组,强调“不可变”和“函数式”风格:
-
map:逐项转换,输出数组长度一定和输入一致
例如:[1,2,3].map(x => x * 2)→[2,4,6] -
filter:逐项判断,只保留符合条件的项
例如:[1,2,3,4].filter(x => x % 2 === 0)→[2,4] - 二者都不能短路,一定会遍历全部元素;若只需判断存在性,改用
some()或every()
性能与实际取舍
纯速度排序通常是:for > for...of > map ≈ filter > forEach,但差异在万级以内几乎不可感:
- 日常开发中,优先按语义选:想“映射”就用 map,想“筛选”就用 filter,想“执行”就用 forEach
- 性能瓶颈真出现时,往往不在遍历本身,而在回调里的逻辑(比如重复计算、DOM 重排)
- 过度优化 forEach 到 for,可能换来更难维护的代码——除非压测证实它是瓶颈











