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

参考资料

相关推荐
奔跑的呱呱牛4 分钟前
CSS Grid 布局参数详解(超细化版)+ 中文注释 Demo
前端·css·grid
木斯佳27 分钟前
前端八股文面经大全:影刀AI前端一面(2026-04-01)·面经深度解析
前端·人工智能·沙箱·tool·ai面经
小江的记录本1 小时前
【Linux】《Linux常用命令汇总表》
linux·运维·服务器·前端·windows·后端·macos
无人机9011 小时前
Delphi 网络编程实战:TIdTCPClient 与 TIdTCPServer 类深度解析
java·开发语言·前端
lUie INGA2 小时前
rust web框架actix和axum比较
前端·人工智能·rust
OPHKVPS3 小时前
VoidStealer新型窃密攻击:首例利用硬件断点绕过Chrome ABE防护,精准窃取v20_master_key
前端·chrome
gechunlian883 小时前
SpringBoot3+Springdoc:v3api-docs可以访问,html无法访问的解决方法
前端·html
驾驭人生3 小时前
ASP.NET Core 实现 SSE 服务器推送|生产级实战教程(含跨域 / Nginx / 前端完整代码)
服务器·前端·nginx
酉鬼女又兒4 小时前
零基础快速入门前端ES6 核心特性详解:Set 数据结构与对象增强写法(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6
慧一居士4 小时前
Vue项目中,子组件调用父组件方法示例,以及如何传值示例,对比使用插槽和不使用插槽区别
前端·vue.js