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

参考资料

相关推荐
coding随想2 小时前
JavaScript ES6 解构:优雅提取数据的艺术
前端·javascript·es6
小小小小宇2 小时前
一个小小的柯里化函数
前端
灵感__idea2 小时前
JavaScript高级程序设计(第5版):无处不在的集合
前端·javascript·程序员
小小小小宇2 小时前
前端双Token机制无感刷新
前端
小小小小宇2 小时前
重提React闭包陷阱
前端
小小小小宇3 小时前
前端XSS和CSRF以及CSP
前端
UFIT3 小时前
NoSQL之redis哨兵
java·前端·算法
超级土豆粉3 小时前
CSS3 的特性
前端·css·css3
星辰引路-Lefan3 小时前
深入理解React Hooks的原理与实践
前端·javascript·react.js
wyn200011283 小时前
JavaWeb的一些基础技术
前端