【js篇】forEach 和 map 方法有什么区别?

58 阅读2分钟

在 JavaScript 中,forEachmap 是数组操作中最常用的两个高阶函数。它们都可以用来遍历数组并对每个元素执行操作,但它们的设计目的和使用场景有本质区别。理解它们之间的差异,有助于我们写出更清晰、更高效的代码。


✅ 一句话总结

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...offor 循环配合 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>']

✅ 三、核心区别对比表

特性forEachmap
返回值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 生成新数据(无副作用)。选择正确的方法,让代码更语义化、更可维护。


💡 最佳实践建议

  1. 数据转换 → 用 map

    const urls = links.map(link => link.href);
    
  2. 执行操作 → 用 forEach

    buttons.forEach(btn => btn.addEventListener('click', handler));
    
  3. 链式调用 → 优先 map

    data
      .filter(item => item.active)
      .map(item => item.name)
      .forEach(name => console.log(name));
    
  4. 避免在 map 中返回 undefined

    // ❌ 浪费 map 的返回能力
    list.map(item => console.log(item));