在 JavaScript 中,forEach 和 map 是数组操作中最常用的两个高阶函数。它们都可以用来遍历数组并对每个元素执行操作,但它们的设计目的和使用场景有本质区别。理解它们之间的差异,有助于我们写出更清晰、更高效的代码。
✅ 一句话总结
forEach用于执行副作用操作(如打印、修改外部变量),不返回新数组;而map用于转换数组元素并返回一个新数组,更适合函数式编程。
✅ 一、forEach 方法详解
🔹 语法
array.forEach(function(element, index, array) {
// 执行操作
});
🔹 特点
- 遍历数组,对每个元素执行提供的函数;
- 没有返回值(返回
undefined); - 适用于执行“副作用”操作,如:
- 修改外部变量
- 操作 DOM
- 发送请求
- 打印日志等
🔹 示例
const numbers = [1, 2, 3];
// 打印每个元素
numbers.forEach(num => console.log(num));
// 累加求和
let sum = 0;
numbers.forEach(num => {
sum += num;
});
console.log(sum); // 6
// 操作 DOM
const elements = document.querySelectorAll('.item');
elements.forEach((el, index) => {
el.textContent = `Item ${index + 1}`;
});
🔹 注意
- 不能使用
return中断循环(return只是跳出当前回调); - 如需中断,应使用
for...of或for循环配合break。
✅ 二、map 方法详解
🔹 语法
const newArray = array.map(function(element, index, array) {
return transformedValue;
});
🔹 特点
- 遍历数组,对每个元素应用函数,并返回一个新数组;
- 原数组保持不变(纯函数、无副作用);
- 适用于数据转换场景,如:
- 数值计算
- 对象属性提取
- 格式化数据
🔹 示例
const numbers = [1, 2, 3];
// 将每个元素乘以 2
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6]
console.log(numbers); // [1, 2, 3] — 原数组未变
// 提取对象的某个属性
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 }
];
const names = users.map(user => user.name);
console.log(names); // ['Alice', 'Bob']
// 格式化为 HTML 字符串
const listItems = users.map(user => `<li>${user.name} (${user.age})</li>`);
console.log(listItems); // ['<li>Alice (25)</li>', '<li>Bob (30)</li>']
✅ 三、核心区别对比表
| 特性 | forEach | map |
|---|---|---|
| 返回值 | undefined | 新数组(长度与原数组相同) |
| 是否修改原数组 | 否(但回调中可修改) | 否 |
| 适用场景 | 执行副作用(打印、DOM 操作、请求等) | 数据转换、生成新数组 |
| 链式调用 | ❌ 不能(返回 undefined) | ✅ 可以(返回数组) |
| 性能 | 略低(无返回值优化) | 略高(现代引擎优化良好) |
| 函数式编程 | 不推荐(有副作用) | 推荐(纯函数) |
✅ 四、常见误用与最佳实践
❌ 错误用法:用 forEach 替代 map
// ❌ 错误:想生成新数组却用 forEach
const doubled = [];
[1, 2, 3].forEach(num => doubled.push(num * 2));
✅ 正确做法:
// ✅ 正确:使用 map
const doubled = [1, 2, 3].map(num => num * 2);
❌ 错误用法:在 map 中执行副作用
// ❌ 不推荐:map 应用于转换,而非副作用
users.map(user => {
console.log(user.name);
sendEmail(user.email); // 副作用
});
✅ 正确做法:
// ✅ 推荐:使用 forEach 执行副作用
users.forEach(user => {
console.log(user.name);
sendEmail(user.email);
});
✅ 五、一句话总结
用
forEach做事情(有副作用),用map生成新数据(无副作用)。选择正确的方法,让代码更语义化、更可维护。
💡 最佳实践建议
-
数据转换 → 用
mapconst urls = links.map(link => link.href); -
执行操作 → 用
forEachbuttons.forEach(btn => btn.addEventListener('click', handler)); -
链式调用 → 优先
mapdata .filter(item => item.active) .map(item => item.name) .forEach(name => console.log(name)); -
避免在
map中返回undefined// ❌ 浪费 map 的返回能力 list.map(item => console.log(item));