我在Firefox-3.5.7/Firebug-1.5.3和Firefox-3.6.16/Firebug-1.6.2中观察到这一点

当我启动Firebug时:

var x = new Array(3) console.log (x) // [undefined, undefined, undefined] Var y = [undefined, undefined, undefined] console.log (y) // [undefined, undefined, undefined] Console.log (x.constructor == y.constructor) // true console.log ( X.map(函数(){返回0;}) ) // [undefined, undefined, undefined] console.log ( Y.map(函数(){返回0;}) ) // [0,0,0]

这是怎么回事?这是一个错误,还是我误解了如何使用新数组(3)?


当前回答

不是bug。这就是Array构造函数的工作方式。

争取民主变革运动:

当您使用Array构造函数指定单个数值形参时,您将指定数组的初始长度。下面的代码创建了一个包含五个元素的数组:

var billingMethod = new Array(5);

Array构造函数的行为取决于单个参数是否为数字。

.map()方法只在数组的迭代元素中包含显式赋值的元素。即使显式赋值为undefined也会导致一个值被认为符合迭代包含的条件。这看起来很奇怪,但它本质上是对象上显式的未定义属性和缺少属性之间的区别:

var x = { }, y = { z: undefined };
if (x.z === y.z) // true

对象x没有名为“z”的属性,而对象y有。然而,在这两种情况下,属性的“值”似乎都是未定义的。在数组中,情况与此类似:length的值隐式地对从0到length - 1的所有元素进行赋值。因此,在使用array构造函数和数值参数新构造的数组上调用.map()函数时,不会执行任何操作(不会调用回调)。

其他回答

我认为最好的解释方式是看看Chrome处理它的方式。

>>> x = new Array(3)
[]
>>> x.length
3

因此,实际发生的情况是new Array()返回一个长度为3的空数组,但没有值。因此,当您在技术上为空的数组上运行x.map时,不需要设置任何内容。

Firefox只是用undefined“填充”这些空槽,即使它没有值。

我不认为这是一个明显的错误,只是一种表现正在发生的事情的糟糕方式。我想Chrome的是“更正确”,因为它显示数组中实际上没有任何东西。

从map的MDC页面:

[…回调函数只对赋值的数组索引调用;[…]

[undefined]实际上应用了索引(es)上的setter,因此map将进行迭代,而new Array(1)只是初始化索引(es),默认值为undefined,因此map跳过它。

我相信这对于所有的迭代方法都是一样的。

我有一个任务,我只知道数组的长度,需要转换项目。 我想这样做:

let arr = new Array(10).map((val,idx) => idx);

快速创建一个这样的数组:

[0,1,2,3,4,5,6,7,8,9]

但这并不奏效,因为: (参见乔纳森·洛诺夫斯基的回答)

解决方案是使用array .prototype.fill()将数组项填充为任何值(甚至是undefined)

let arr = new Array(10).fill(undefined).map((val,idx) => idx);

console.log(新数组(10).fill(定义)。Map ((val, idx) => idx));

更新

另一个解决方案是:

let arr = Array.apply(null, Array(10)).map((val, idx) => idx);

console.log(数组。应用(null,数组(10))。Map ((val, idx) => idx));

在ECMAScript第6版规范。

new Array(3)只定义属性长度,不定义索引属性如{length: 3}。参见https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len步骤9。

[undefined, undefined, undefined]将定义索引属性和长度属性,如{0:undefined, 1: undefined, 2: undefined, length: 3}。参见https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulation ElementList步骤5。

方法map, every, some, forEach, slice, reduce, reduceRight, Array的filter将通过HasProperty内部方法检查索引属性,因此new Array(3)。Map (v => 1)将不会调用回调函数。

更多详细信息,请参见https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map

如何修复?

let a = new Array(3);
a.join('.').split('.').map(v => 1);

let a = new Array(3);
a.fill(1);

let a = new Array(3);
a.fill(undefined).map(v => 1);

let a = new Array(3);
[...a].map(v => 1);

由于在其他答案中详细解释的原因,数组(n)。地图不能用。然而,在ES2015中Array.from接受一个map函数:

let array1 = Array.from(Array(5), (_, i) => i + 1) console.log('array1', JSON.stringify(array1)) // 1,2,3,4,5 .log('array1', JSON.stringify(array1) 让array2 = Array.from({长度:5},(_,我)= > (i + 1) * 2) console.log('array2', JSON.stringify(array2)) // 2,4,6,8,10 .log('array2', JSON.stringify(array2)