数组中 forEach 和 Map 的区别

定义

MDN上对Map和ForEach的定义

forEach(): 对数组的每个元素执行一次给定的函数。

map(): 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成

forEach 

语法

arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

参数

  • callback

    为数组中每个元素执行的函数,该函数接收一至三个参数:

    • currentValue   数组中正在处理的当前元素。

    • index 可选   数组中正在处理的当前元素的索引。

    • array 可选   forEach() 方法正在操作的数组。

  • thisArg 可选

    可选参数。当执行回调函数 callback 时,用作 this 的值。

返回值

undefined

案例

let arr = ['a','b','c']
// 回调函数接受3个参数
// 数组的当前值作为第一个参数
// 当前值在数组中的位置作为第二个参数
// 原始源数组作为第三个参数

let cb = (item,index,originArr) => {
    console.log(item + ':' + index + '/' + originArr);
}
arr.forEach(cb)
/* 
a:0/a,b,c
b:1/a,b,c
c:2/a,b,c
*/

特性

1.forEach()方法没有返回值

var a = [1,2,3]
var b = a.forEach((item) => {
    item = item * 2
})
console.log(b) // undefined

2.forEach()方法也会跳过数组的空位

var a = [null, , undefined]
for (let i = 0; i < a.length; i++) {
    console.log('a', a[i]) // null undefined undefined
}
a.forEach(item => {
    console.log('item', item) // null undefined
});

改变数组值的情况

情况一:修改item的值,原数组没有发生改变

let a = [1,2,3]
a.forEach((item) => {
    item = item * 2
})
console.log(a) // [1,2,3]

情况二:修改item的值,依然没有修改原数组。

let a = [1,'2',{c:1},true] 
a.forEach((item, index, arr) => {
    item = 5 
}) 
console.log(a) // [1,'2',{c:1},true]

情况三:修改数组中对象的某个属性时,发现属性改变了。其他值依旧没有改变。

let a = [1,'2',{c:1},true] 
a.forEach((item, index, arr) => { 
    item.c = 2 
    item = 2
}) 
console.log(a)  // [1,'2',{c:2},true]

改变数组的原理

对于JS中的基本数据类型,如 String,Number,Boolean,Undefined,Null,Symbol,BigInt 是存在于栈内存中的,在栈内存中储存变量名及相应的值。

对于引用数据类型Object,Array,Function,在栈中存储了指针,该指针指向堆中该实体的起始地址 。

  • 在第一个例子中,为什么直接修改item无法修改原数组呢,因为item的值并不是相应的原数组中的值,而是重新建立的一个新变量,值和原数组相同。因此,如果item是基础数据类型,那么并不会改变数组里面的值,如果是引用类型,那么item和数组里面的值是指向同一内存地址,则都会被改变。
  • 在第二个例子中,数组中的对象的值也没有改变,是因为新创建的变量和原数组中的对象虽然指向同一个地址,但改变的是新变量的值,也就是重新赋值,即新对象的值为2,原数组中的对象还是{num:1}。
  • 在第三个例子中,由于对象是引用类型,新对象和旧对象指向的都是同一个地址,所以新对象把num变成了2,原数组中的对象也改变了。

map

map 的作用与 for 循环完全相同,只是 map 会创建一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。

语法

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
 // Return element for new_array
}[, thisArg])

参数

  • callback

    生成新数组元素的函数,使用三个参数:

    • currentValue callback 数组中正在处理的当前元素。

    • index可选 callback 数组中正在处理的当前元素的索引。

    • array可选 map 方法调用的数组。

  • thisArg可选

    执行 callback 函数时值被用作this

返回值

一个由原数组每个元素执行回调函数的结果组成的新数组。

案例

let arr = [1,2,3]
let newArr = arr.map(item => item + 1)
console.log(newArr); //[ 2, 3, 4 ]
console.log(arr); //[ 1, 2, 3 ]

从上面案例可知,返回一个经过处理后的新数组,但不改变原数组的值。

map也会跳过空位

var a = [null, , undefined]
for (let i = 0; i < a.length; i++) {
    console.log('a', a[i]) // null undefined undefined
}
a.map(item =>{
    console.log('item', item)// null undefined 
})

改变数组情况

map中可改变原数组的情况和原理与forEach相同

区别

forEach()方法不会返回执行结果,而是返回undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。

使用场景

因为 map 和 forEach 的主要区别是有无返回,所以,当你想基于一个原数组返回一个新数组,可以选择 map,当你只是想遍历数据不需要考虑返回时可以选择 forEach。

参考资料:forEach、map和for循环 - 掘金

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值