控制台里跑一段数组遍历,forEach 里写了 return,本想让循环提前停下,结果后面的元素照样打印。翻文档才发现,forEach 压根不支持 break。

写法不复杂:arr.forEach(function(item, index, array){}),箭头函数也行。item 是当前元素,index 是下标,第三个参数是原数组。返回值固定是 undefined,所以别写 const result = arr.forEach(...),拿到的永远是空。

const nums = [1, 2, 3];
nums.forEach((n, i) => {
  console.log(i, n * 2);
});

想中途退出只能换方法

forEach 里 return 只相当于 continue,跳过当前这一轮,后面的照跑。要真正中断,用 for 循环、for...of,或者 some、every 这类能靠返回值停下的方法。some 找到符合条件的就停,every 遇到 false 就停,很多人拿它们当「带 break 的 forEach」。

await 写在里面不会等

forEach 的回调是普通函数调用,外层不会等 Promise。里面写 await 上传文件,循环瞬间跑完,请求全堆在后面。要按顺序处理,改成 for...of,或者用 for await...of。要并发,用 Promise.all 配合 map,别指望 forEach 帮你排队。

空位和长度变化

稀疏数组的空位会被跳过,[1, , 3] 只遍历两次,下标是 0 和 2。遍历过程中 push 的新元素不会被执行,删除元素则可能导致后面的项被跳过。想边遍历边改数组,老老实实用倒序 for 循环。

还有两个小点:forEach 不能直接用在 arguments 上,得先转成数组;NodeList 在现代浏览器里有 forEach,但 IE 没有。性能上 for 循环确实快一点,普通列表这点差距可以忽略,真要处理几十万条数据再考虑换写法。

判断标准很简单:只是对每一项做点事,forEach 够用;需要中断、需要顺序等待、需要返回新数组,就换 for、for...of 或者 map。js foreach 本身不难,难的是别把它当成万能循环。