JS map的怪癖

2019-04-11

JS map的怪癖

map是数组处理的常用函数式方法,MDN对map()的解释如下:

map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values, including undefined. It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).

map()签名为:

map(callback(currentValue[, index[, array]]):newValue [, thisArg])
  • callback用来生成新值的function
  • thisArg为可选的this绑定对象

其中,MDN的解释中提了一嘴这样的话:

callback is invoked only for indexes of the array which have assigned values, including undefined.

这就造成了map的一个怪癖:map在处理数组时会跳过没有被assign过的数组位置

实例1

const array1 = new Array(3);

const array2 = array1.map(()=>'mapped')

console.log(array2);

这里会输出什么呢?一个length为3的数组按理说应该输出

['mapped', 'mapped','mapped']

实质上输出:

[ <3 empty items> ]

原因:3个位置都没有被assign过,map都跳过了

实例2

const array1 = new Array(3);

array1[1] = undefined;

const array2 = array1.map(()=>'mapped')

console.log(array2);

输出:

[ <1 empty item>, 'mapped', <1 empty item> ]

因为只有array1[1]经过了assign,即使是assign了一个undefined,所以只在这个位置上调用了map。

容易混淆的点

在node中,array没有赋值的位置显示为<empty>,是为了容易分辨unassignedassigned undefined,实际上JS并没有这个数据类型,在一些环境中都是undefiend。

const array1 = new Array(3);

console.log(array1[0]===undefined);
//true

如以上代码所示。

解决方法

对于数组填充操作,使用Array.prototype.fill()而不是妄想使用map