Javascript中数组方法map和forEach的对比

在学习Javascript繁多的数组方法时,mapforEach两个方法经常被拿来对比,两者用法比较相似但在一些细节上又有所区别.JS高程3对二者叙述分别如下:

forEach():对数组中的每一项运行给定函数,这个方法没有返回值

map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组.

两者区别

1. 返回值不同

  • map() : 返回一个新数组,包含回调函数对每个元素的处理结果

    javascript 复制代码
    const numbers = [1, 2, 3];
    const doubled = numbers.map(num => num * 2);
    console.log(doubled); // [2, 4, 6]
  • forEach() : 没有返回值(返回 undefined

    javascript 复制代码
    const result = numbers.forEach(num => num * 2);
    console.log(result); // undefined

2.在回调中显式修改原数组时的差异

在 JavaScript 中,map()forEach() 方法本身不会自动修改原始数组,但它们确实提供了在回调函数中修改原数组的可能性。这种修改就是"显式修改"。

2.1. 不修改原数组的正常用法

javascript 复制代码
const numbers = [1, 2, 3];

// map - 不修改原数组
const doubled = numbers.map(num => num * 2);
console.log(numbers); // [1, 2, 3] (未改变)
console.log(doubled); // [2, 4, 6]

// forEach - 不修改原数组
numbers.forEach(num => num * 2);
console.log(numbers); // [1, 2, 3] (未改变)

2.2. 显式修改原数组的情况

javascript 复制代码
const numbers = [1, 2, 3];

// 在forEach回调中显式修改原数组
numbers.forEach((num, index, arr) => {
  arr[index] = num * 2; // 显式修改原数组
});
console.log(numbers); // [2, 4, 6] (已改变)

// 在map回调中显式修改原数组
const anotherArray = [1, 2, 3];
const result = anotherArray.map((num, index, arr) => {
  arr[index] = num + 1; // 显式修改原数组
  return num * 2;
});
console.log(anotherArray); // [2, 3, 4] (已改变)
console.log(result); // [2, 4, 6] (map仍返回新数组)

注意事项

  1. 不推荐这样做:显式修改原数组会使代码难以理解和维护
  2. 可能导致意外行为:特别是在链式调用时
  3. 考虑使用其他方法 :如果需要修改原数组,可以考虑 splice、直接赋值等更明确的方式
  • map() 方法返回一个全新的数组,其中包含转换后的元素和相同数量的数据。这类似于React修改state时要保持不可变性一样.因而callback最好遵循纯函数原则.

  • 对于 forEach() ,即使它返回 undefined,它也会用 callback 改变原始数组。同样类比于React,使用forEach不用遵循不可变性,因而可以在callback里面使用副作用.

小结一下,我们可以理解为 map() 依赖于不变性,而 forEach() 是一个 mutator 方法。

3.是否能链式调用

  • map() : 可以链式调用其他数组方法
  • forEach() : 不能链式调用,因为它返回 undefined
javascript 复制代码
const myAwesomeArray = [1, 2, 3, 4, 5]
myAwesomeArray.forEach(x => x * x).reduce((total, value) => total + value)
//>>>>>>>>>>>>> Uncaught TypeError: Cannot read property 'reduce' of undefined
myAwesomeArray.map(x => x * x).reduce((total, value) => total + value)
//>>>>>>>>>>>>>return value: 55

4.性能差异

  • map() : 稍慢于 forEach(),因为它需要创建并返回新数组
  • forEach() : 性能稍好,适合纯遍历场景

参考资料

相关推荐
祯民1 分钟前
《生成式 AI 应用开发:基于 OpenAI API 开发》实体书上架
前端·aigc·openai
bigyoung6 分钟前
ts在运行时校验数据类型的探索
前端·javascript·typescript
独立开阀者_FwtCoder10 分钟前
深入解密Node共享内存:这个原生模块让你的多进程应用性能翻倍
前端·javascript·后端
Json_11 分钟前
使用JS写一个用鼠标拖动DIV到任意地方
前端·javascript·深度学习
祯民16 分钟前
阿民解锁了"入职 30 天跑路"新成就
前端·面试
昌平第一王昭君17 分钟前
一个简单的虚拟滚动
前端
Json_19 分钟前
jQuery选项卡小练习
前端·深度学习·jquery
王sir万岁23 分钟前
普通前端工程师如何入门 Web3 开发?
前端
Json_25 分钟前
2017-06-05 20:33:39发布第一篇博客 坚持写博客时间统计代码(某个时间到当前时间的统计)
前端·深度学习
王sir万岁27 分钟前
React + Vite + CSS-in-JS + SSR 开发最佳实践
前端