定义
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。