forEach用于执行副作用且不改变原数组,map用于转换数据并返回新数组;前者无返回值,后者必须return否则结果为undefined。

forEach 不会改变原数组,但 map 会返回一个新数组
这是最根本的区别:forEach 只用来“执行副作用”,比如修改外部变量、发请求、打日志;map 的设计目标是“转换数据”,它必须返回每个元素的映射结果,并把所有结果组装成一个新数组。
常见错误现象:用 map 去做纯遍历(比如只调用 console.log),却忽略它返回了一个满是 undefined 的数组——这既浪费内存,又容易在后续链式调用中引发 TypeError。
-
forEach返回值固定是undefined,不能链式调用 -
map返回新数组,可直接接filter、reduce等 - 如果只是想遍历并修改原数组某字段,
forEach更直观;如果要生成结构不同的新数组(如提取id、转为对象、加前缀),必须用map
map 的回调函数必须有 return,forEach 则不需要
map 的每个迭代项都依赖回调的返回值来构建新数组。漏写 return,对应位置就是 undefined;而 forEach 的回调即使写了 return,也对遍历过程无影响。
const arr = [1, 2, 3];
const doubled = arr.map(x => x * 2); // [2, 4, 6]
const broken = arr.map(x => { x * 2 }); // [undefined, undefined, undefined]
arr.forEach(x => console.log(x)); // 正常打印 1 2 3
arr.forEach(x => { return x * 2 }); // 没报错,但也没任何效果
性能和兼容性几乎没差别,但语义不可互换
两者底层都是循环,时间复杂度都是 O(n),现代引擎优化程度也相当。真正要注意的是语义误用带来的维护成本:
立即学习“Java免费学习笔记(深入)”;
- 用
forEach实现本该用map的逻辑(比如手动push到空数组),代码更啰嗦,且失去函数式表达力 - 用
map替代forEach处理副作用,会产生无意义的新数组,可能触发意外的 GC 或内存泄漏(尤其在大数据量或高频调用场景) - IE9+ 支持两者,无需 polyfill;但若需支持 IE8,两个方法都要自行实现或引入
es5-shim
什么时候该选 for...of 或传统 for 循环?
当需要提前退出(break)、跳过本次(continue)、或访问索引/原数组引用时,forEach 和 map 都不适用——它们无法中断。
const arr = [1, 2, 3, 4, 5];
// 想找到第一个大于 3 的数就停,forEach/map 做不到
for (const item of arr) {
if (item > 3) {
console.log(item); // 4
break;
}
}
// 需要同时操作索引和元素,且要 break,传统 for 最直接
for (let i = 0; i < arr.length; i++) {
if (arr[i] > 3) {
console.log(i, arr[i]); // 3 4
break;
}
}
实际编码中,最容易被忽略的是:是否真的需要返回值。看到“遍历数组”,第一反应不该是选 forEach 还是 map,而是先问自己——这次操作的产出是什么?是动作(log、fetch、DOM 更新),还是数据(新数组、计算结果)?答案决定了该用哪个。











