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 分钟前
📝 深入浅出 JavaScript 拷贝:从浅拷贝到深拷贝 🚀
前端
中微子18 分钟前
闭包面试宝典:高频考点与实战解析
前端·javascript
brzhang18 分钟前
前端死在了 Python 朋友的嘴里?他用 Python 写了个交互式数据看板,着实秀了我一把,没碰一行 JavaScript
前端·后端·架构
G等你下课1 小时前
告别刷新就丢数据!localStorage 全面指南
前端·javascript
该用户已不存在1 小时前
不知道这些工具,难怪的你的Python开发那么慢丨Python 开发必备的6大工具
前端·后端·python
爱编程的喵1 小时前
JavaScript闭包实战:从类封装到防抖函数的深度解析
前端·javascript
LovelyAqaurius1 小时前
Unity URP管线着色器库攻略part1
前端
Xy9101 小时前
开发者视角:App Trace 一键拉起(Deep Linking)技术详解
java·前端·后端
lalalalalalalala1 小时前
开箱即用的 Vue3 无限平滑滚动组件
前端·vue.js
前端Hardy1 小时前
8个你必须掌握的「Vue」实用技巧
前端·javascript·vue.js