我在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)?


当前回答

在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);

其他回答

刚碰到这个。使用Array(n).map肯定会很方便。

数组(3)大致生成{length: 3}

[undefined, undefined, undefined]创建有编号的属性: {0:未定义,1:未定义,2:未定义,长度:3}。

map()实现仅作用于已定义的属性。

ES6解决方案:

[...Array(10)]

但不能在typescript(2.3)上工作

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

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

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

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

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

看来第一个例子

x = new Array(3);

创建一个长度为3但没有任何元素的数组,因此不会创建索引[0]、[1]和[2]。

第二个创建了一个包含3个未定义对象的数组,在这种情况下,它们自己的索引/属性被创建,但它们引用的对象是未定义的。

y = [undefined, undefined, undefined]
// The following is not equivalent to the above, it's the same as new Array(3)
y = [,,,];

因为map在索引/属性列表上运行,而不是在设置的长度上运行,所以如果没有创建索引/属性,它将不会运行。

既然问题是为什么,这与JS的设计方式有关。

我认为有两个主要原因可以解释这种行为:

性能:给定x = 10000和新Array(x),构造函数最好避免从0到10000循环填充未定义值的数组。 隐式"undefined":给定a = [undefined, undefined]和b = new Array(2), a[1]和b[1]都将返回undefined,但a[8]和b[8]即使超出范围也将返回undefined。

最终,符号empty x3是避免设置和显示一长串未定义值的快捷方式,因为它们没有显式声明。

注意:给定数组a =[0]和[9]= 9,console.log(a)将返回(10)[0,empty x 8,9],通过返回显式声明的两个值之间的差值自动填充空白。