作用
map()
:创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
语法
arr.map(callback(currentValue [, index [, array]]){ // Return element for new_array }[, thisArg])
callback
:生成新数组元素的函数,该函数接收一至三个参数:currentValue
:数组中正在处理的当前元素。index
: 可选,数组中正在处理的当前元素的索引。array
: 可选,map
方法正在操作的数组。
thisArg
: 可选,执行 callback
函数时值被用作 this
返回值:一个由原数组每个元素执行回调函数的结果组成的新数组。
map
方法会给原数组中的每个元素都按顺序调用一次callback
函数。callback
每次执行后的返回值(包括undefined
)组合起来形成一个新数组。callback
函数只会在有值的索引上被调用;那些从来没被赋过值或者使用delete
删除的索引则不会被调用。map
不修改调用它的原数组本身(当然可以在callback
执行时改变原数组)
因为
map
生成一个新数组,当你不打算使用返回的新数组却使用请用forEach
或者for-of
替代。
使用示例
求数组中每个元素的平方根
const numbers = [1, 4, 9];
const roots = numbers.map(Math.sqrt);
console.log(roots); // [1, 2, 3]
上述的代码在 map
中传入了一个 Math.sqrt
然后就计算出了 numbers 每个元素的平方根,那么它是如何实现的?
看如图所示,可以发现 Math.sqrt
实际上是一个函数,然后接收一个 number
类型的参数,在此示例中可以这么认为
const roots = numbers.map(function (item) {
// 这里面就是 Math.sqrt 函数做的操作,它将返回每一个 item 的平方根
});
返回的数组元素中存在 undefined
const numbers = [1, 2, 3, 4, 5];
const filteredNumbers = numbers.map(function (num, index) {
if (index < 3) {
return num;
}
});
console.log(filteredNumbers);
在 map 中改变了原数组
基础数据类型的数组,如代码与结果所示,基础类型的数组在修改 item
时并不会改变原数组。
是因为 map
方法处理数组元素的范围是在 callback
方法第一次调用之前就已经确定了。
const arr = [1, 5, 10, 15, 66, 200];
const newArr = arr.map(function (item) {
if (item > 15) {
item += 1
}
return item
});
console.log(arr);
console.log(newArr);
对象数组,如代码与结果所示,对象数组在修改 item
时会改变原数组
const arr = [
{ name: 'wfly', age: 18 },
{ name: 'fly', age: 8 },
{ name: 'fnn', age: 18 },
];
const newArr = arr.map(function (item) {
if (item.name.includes('fly')) {
item.age += 1
}
return item
});
console.log(arr);
console.log(newArr);
使用过程中直接改变原数组
map
方法处理数组元素的范围是在callback
方法第一次调用之前就已经确定了。- 调用
map
方法之后 追加 的数组元素不会被callback
访问。 - 如果存在的数组元素改变了,那么传给
callback
的值是map
访问该元素时的值。在map
函数调用后但在访问该元素前,该元素被删除的话,则无法被访问到。
const arr = [3, 5, 10, 15, 66, 200];
const newArr = arr.map(function (item, index) {
arr[index] = arr[index] + 10
arr.push(999)
console.log('当前 arr 的值:', arr);
arr.unshift(111)
return item
});
console.log(arr);
console.log(newArr);
如结果所示,会发现 newArr
输出的是 [3, 13, 23, 33, 43, 53]
,为什么会造成这种现象,
我们在示例代码中每一次 callback
的执行,都会将原数组的 arr
对象的 index
项 +10
,同时我们每一次执行 callback
都会在给原数组 push
一个元素以及 unshift
的一个元素
当然由于 push
是在尾部添加,它不会被 callback
所访问,但是 unshift
是在头部添加,会导致原数组之前的元素每执行一次 callback
都会向后移一项
由于 callback
的 item
,每次都是访问当前项的元素,而恰好 3
这个元素每次都是 +10
然后向后移一项,
所以得出结果 [3, 13, 23, 33, 43, 53]
所以上述的代码示例如果没有添加 unshift 去改变原数组的话,输出的结果就是
[3, 5, 10, 15, 66, 200]
map
+ parseInt
问题
["1", "2", "3"].map(parseInt); // [1, NaN, NaN]
如果看完第一个示例这个问题就很容易明白,parseInt 是一个函数,但是它接受的参数是两个,所以它不会输出 [1, 2, 3],
它在处理时实际上是 parseInt(1, 0)
,parseInt(2, 1)
,parseInt(3, 2)
,第一项参数是数组的 item
,第二个参数是当前数组的索引
正确的处理方法应该如下
['1', '2', '3'].map(str => parseInt(str));