forEach 按索引升序遍历已存在元素,跳过稀疏空位;不响应遍历中数组修改,无法中断循环;不改变原数组但允许回调内修改;不支持类数组和空数组,无返回值,适用于纯副作用操作。

forEach 是 JavaScript 中最常用的数组遍历方法之一,但它不是“万能循环”,有明确的遍历规则和不可忽视的限制。
遍历顺序严格按索引升序执行
forEach 会从索引 0 开始,依次访问数组中已存在(即非稀疏)的元素,直到最后一个有效索引。它不跳过空位,但会跳过未定义的稀疏项(如 [1, , 3] 中的第二个位置)。
- 对稀疏数组(如
new Array(3)或[1, undefined, 3]),只有实际赋值的索引会被回调 - 如果数组在遍历中被修改(如 push、splice),新增的元素不会被访问,已访问过的索引也不会重复执行
- 遍历过程中删除前面的元素,后续元素索引前移,但 forEach 仍按原始索引快照执行——也就是说,它“看不见”移动后的变化
无法中断或跳出循环
forEach 没有类似 break 或 return false 的中断机制。在回调中使用 return 只会退出当前回调函数,下一项仍会继续执行。
- 想提前终止?改用
for...of、for循环或some()/every()(利用其返回值逻辑) - 常见误写:
arr.forEach(x => { if (x === target) return; doSomething(); })—— 这不会停止遍历
不改变原数组,但回调内可修改
forEach 本身不会修改数组长度或结构,但你在回调函数中直接操作原数组(如 arr[i] = newValue 或 arr.push())是完全允许的,只是这些改动不影响本次遍历行为。
立即学习“Java免费学习笔记(深入)”;
- 可以安全地更新当前元素值:
arr.forEach((v, i) => arr[i] = v * 2) - 避免在遍历时用
splice()删除当前项附近元素,易导致漏处理或重复处理(因索引错位) - 不要依赖 thisArg 修改外部变量来“控制流程”,它仅用于绑定回调中的
this
不兼容空数组与类数组,且无返回值
forEach 对空数组静默执行零次;对类数组对象(如 arguments、DOM 集合)不能直接调用,必须先转为真数组(Array.from() 或 [...arr])。
- 它始终返回
undefined,不能链式调用(比如不能接.map()或.filter()) - 需要边遍历边收集结果?优先选
map()、filter()或reduce() - 纯副作用操作(如发请求、改 DOM、打日志)才是 forEach 的典型场景










