map详解与实战

map() (映射)方法最后生成一个新数组,不改变原始数组的值。其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

1
array.map(callback, [thisObject]);

callback(回调函数)

1
2
3
[].map(function (currentValue, index, array) {
// ...
});

传递给 map 的回调函数(callback)接受三个参数,分别是 currentValue——正在遍历的元素、index(可选)——元素索引、array(可选)——原数组本身,除了 callback 之外还可以接受 this 值(可选),用于执行 callback 函数时使用的 this 值。

来个简单的例子方便理解,现在有一个数组[1, 2, 3, 4],我们想要生成一个新数组,其每个元素皆是之前数组的两倍,那么我们有下面两种使用高阶和不使用高阶函数的方式来实现。

不使用高阶函数

1
2
3
4
5
6
7
8
9
10
const arr1 = [1, 2, 3, 4];
const arr2 = [];
for (let i = 0; i < arr1.length; i++) {
arr2.push(arr1[i] * 2);
}

console.log(arr2);
// [2, 4, 6, 8]
console.log(arr1);
// [1, 2, 3, 4]

使用高阶函数

1
2
3
4
5
6
7
const arr1 = [1, 2, 3, 4];
const arr2 = arr1.map((item) => item * 2);

console.log(arr2);
// [2, 4, 6, 8]
console.log(arr1);
// [1, 2, 3, 4]

map 高阶函数注意点

callback 需要有 return 值,否则会出现所有项映射为 undefind;

1
2
3
4
5
6
7
const arr1 = [1, 2, 3, 4];
const arr2 = arr1.map((item) => {});

console.log(arr2);
// [ undefined, undefined, undefined, undefined ]
console.log(arr1);
// [1, 2, 3, 4]

map 高阶函数对应的一道经典面试题

1
2
//输出结果
["1", "2", "3"].map(parseInt);

看了这道题不知道会不会有大多数开发者认为输出结果是[1,2,3],错误!

正确的输出结果为:

1
[1, NaN, NaN];

分析与讲解
因为 map 的 callback 函数有三个参数,正在遍历的元素, 元素索引(index), 原数组本身(array)。parseInt 有两个参数,string 和 radix(进制)。只传入 parseInt 的话,map callback 会自动忽略第三个参数 array。而 index 参数不会被忽略。而不被忽略的 index(0,1,2)就会被 parseInt 当做第二个参数。

将其拆开看:

1
2
3
parseInt("1", 0); //上面说过第二个参数为进制,所以"1",0会被忽略,按照,parseInt默认的型的1。
parseInt("2", 1); //此时将2转为1进制数,由于超过进制数1,所以返回NaN。
parseInt("3", 2); //此时将3转为1进制数,由于超过进制数1,所以返回NaN。

所以最终的结果为[1,NaN,NaN]。

那么如果要得到[1,2,3]该怎么写。[“1”,”2”,”3”].map((x)=>{ return parseInt(x); }); 也可以简写为:[“1”,”2”,”3”].map(x=>parseInt(x));

这样写为什么就能返回想要的值呢?因为,传一个完整函数进去,有形参,有返回值。这样就不会造成因为参数传入错误而造成结果错误了,最后返回一个经纯函数处理过的新数组。