likes
comments
collection
share

JavaScript 中的map()和forEach():详尽解析与对比

作者站长头像
站长
· 阅读数 24

1. map()和forEach()的区别和理解

Array.prototype.map()Array.prototype.forEach()都是用于遍历数组中的每一项,但它们有一些区别。

在JavaScript的数组操作中,map()forEach() 是两个非常实用的方法,它们都能遍历数组中的每一个元素,但它们之间存在一些重要的区别,这些差异决定了在不同场景下应该选择哪一个方法。接下来,我们将通过定义、实例、共同点及差异点四个方面,全面剖析这两个方法。到底有什么区别呢?

MDN上对Map和ForEach的定义

  • forEach(): 针对每一个元素执行提供的函数(executes a provided function once for each array element)。除了抛出异常以外,没有办法中止或跳出 forEach() 循环。如果你需要中止或跳出循环,forEach() 方法不是应当使用的工具。 map(): callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。
  • map(): 创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来(creates a new array with the results of calling a provided function on every element in the calling array)。map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。

实例

让我们通过具体的代码实例来直观感受两者的用法和效果。

使用 map()
const numbers = [1, 4, 9, 16];
const doubledNumbers = numbers.map(number => number * 2);
console.log(doubledNumbers); // 输出:[2, 8, 18, 32]
console.log(numbers);        // 输出:[1, 4, 9, 16],原数组未变

在上面的例子中,map() 将每个元素乘以2,并返回了一个新数组。

使用 forEach()
const letters = ['a', 'b', 'c'];
let result;
letters.forEach(letter => {
  console.log(letter);
  result = letter.toUpperCase();
});
console.log(result);         // 输出:undefined
console.log(letters);        // 输出:['a', 'b', 'c'],原数组未变

这里,forEach() 只负责遍历和打印每个字母,最终的 resultundefined,因为它不返回任何值。

共同点

  • 循环遍历:两者都会遍历数组的每个元素。
  • 参数传递:都可以接收一个回调函数,该函数可以获取到当前元素item、当前索引index和原始数组input
  • this绑定:回调函数中的 this 默认绑定为全局对象(在浏览器中通常是 window)。

差异点

1.map

  • 有返回值,可以return出来一个length和原数组一致的数组(内容可能包含undefined、null等)
const array = [1,2,4,6,10]; 
const res = array.map((item,index,input) => { return item*10; }) 
console.log(res); // [10,20,40,60,100] 
console.log(array); // [1,2,4,6,10] 不变
  • 参数:item数组中的当前项,index当前项的索引,input原始数组
  • 区别:map的回调函数中支持return返回值,return的是一个数组,相当于把数组中的这一项进行改变(并不影响原来的数组,只是相当于把原数组克隆了一份,把克隆这一份的数组中的对应项改变了 );

2.forEach

  • 没有返回值,返回结果为undefined
const array = [1,2,4,6,10]; 
const res = array.forEach((item,index,input) => {
    return input[index] = item*10; 
}) 
console.log(res); // undefined 
console.log(array); // [10,20,40,60,100]原数组修改为变动后
  • 参数:item数组中的当前项,index当前项的索引,input原始数组;
  • 数组中有几项,那么传递进去的匿名回调函数就需要执行几次 理论上这个方式是没有返回值的,只是遍历数组中的每一项,不对原来数组进行修改,但是可以自己通过数组的索引来修改原来的数组
- 其实上面结果输出是有问题的

JavaScript 中的map()和forEach():详尽解析与对比

forEach 循环中,对于数组 ['a', 'b', 'c'] 的每个元素,都会执行一次箭头函数。在这个函数中,letter.toUpperCase() 被调用以将当前字母转换成大写,然后这个大写形式的字母被赋值给 result

  • 第一次迭代:letter 是 'a'result 设置为 'A'
  • 第二次迭代:letter 是 'b'result 设置为 'B'
  • 第三次迭代:letter 是 'c'result 设置为 'C'

由于 result 是一个变量,它可以在每次迭代中更新其值。在最后一次迭代后,result 的值保持为 'C',这就是为什么在循环结束后打印 result 会输出 'C' 的原因。

尝试使用 map() 循环,通过索引修改原数组值

  • 理论上,map() 不会修改原数组,但如果在回调函数中通过索引访问并修改原数组,会发生什么呢?
Javascript
深色版本
const array = [1, 2, 4, 6, 10];
const res = array.map((item, index, input) => {
    input[index] = item * 10;
});
5console.log(res);       // 输出:[undefined, undefined, undefined, undefined, undefined]
6console.log(array);     // 输出:[10, 20, 40, 60, 100],原数组被修改
  • 从这段代码中我们可以看到,map() 返回的数组由 undefined 组成,因为回调函数中并没有返回任何值。然而,原数组 array 被修改了,这是因为我们在回调函数中通过索引修改了它。

总结

forEach() 方法不会返回执行结果,而是返回 undefined。它被调用时,不会改变原数组,尽管在回调函数中可以修改原数组。

map() 方法会分配内存空间存储新数组并返回。map() 不修改调用它的原数组本身,但在回调执行时可以改变原数组。

了解这些细节对于正确使用这两个方法以及优化代码性能至关重要。在编写代码时,根据你是否需要返回一个新的数组,或者是否需要执行一些副作用操作,选择正确的迭代方法。

转载自:https://juejin.cn/post/7391744486978207794
评论
请登录