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() : 性能稍好,适合纯遍历场景

参考资料

相关推荐
陈天伟教授8 分钟前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看1 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
Tony Bai1 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端
苏打水com1 小时前
第十四篇:Day40-42 前端架构设计入门——从“功能实现”到“架构思维”(对标职场“大型项目架构”需求)
前端·架构
king王一帅1 小时前
流式渲染 Incremark、ant-design-x markdown、streammarkdown-vue 全流程方案对比
前端·javascript·人工智能
苏打水com2 小时前
第十八篇:Day52-54 前端跨端开发进阶——从“多端适配”到“跨端统一”(对标职场“全栈化”需求)
前端
Bigger2 小时前
后端拒写接口?前端硬核自救:纯前端实现静态资源下载全链路解析
前端·浏览器·vite
BD_Marathon2 小时前
【JavaWeb】路径问题_前端绝对路径问题
前端
whyfail3 小时前
Vue原理(暴力版)
前端·vue.js