为什么JavaScript数组索引最大只能是4294967294而不是4294967295?

14
JavaScript 的索引是 32 位的,因此数组的索引应该能够达到 4294967295,共计 4294967296 个元素。但实际上,最大的索引是 4294967294。由于数组有一个 length 属性,我不明白为什么要将最后一个元素设置为 null。那么为什么最大索引是 4294967294 而不是 4294967295 呢?

密切相关:Javascript中数组的最大大小 - Bergi
3个回答

15

这是因为当您使用Array构造函数创建数组时,可以按以下方式提供可选的length

new Array(length);

数组的length是一个32位无符号整数。因此,数组的长度可以从0Math.pow(2, 32) - 1(即4294967295)。

对于长度为n的数组,索引范围从0n - 1。因此,JavaScript数组的最大索引是(Math.pow(2, 32) - 1) - 1或者Math.pow(2, 32) - 2,即4294967294

因此,JavaScript数组最多可以容纳4294967295个元素,而不是4294967296个元素。

我知道这很不合逻辑,但再增加一个元素也不会有太大区别。


2
我不确定这是否在技术上是正确的。虽然长度限制为4294967295(否则会抛出RangeError),但我认为.length本身不是32位UInt。实际上,Chrome告诉我数组对象的.length类型是数字,它的MAX_VALUE比4294967295大得多。 - NullUserException
2
@NullUserException 不要将构造函数参数与属性获取器混淆。此外,仅因为“length”属性的类型是“number”并不意味着它可以取任何可能的值。例如,“typeof Math.sin(x)”也是“number”... - user123444555621
1
@Pumbaa80 我已经研究了一些资料,JavaScript仅具有一个数字类型:Number,它是IEEE 754 double类型。这意味着它对于从-2^53到2^53的所有整数都是准确的。 ToInt32ToUint32等都是抽象操作,不是语言的一部分,只用于规范。这意味着没有像这个答案所建议的无符号整数(或任何种类的整数),因此是错误的。 - NullUserException
3
JavaScript是一种解释性语言,因此数据的内部表示受解释器控制。规范只定义了一个数字数据类型 - Number,它是IEEE 754双精度浮点数,因此在内部被表示为如此。但是,规范将数组的length范围定义为32位无符号整数。因此,解释器可以进行优化并在内部将其存储为如此。访问时,整数被强制转换为Number。这取决于语言实现,可能会有所不同。 - Aadit M Shah
关于我上面的评论:我猜SO不再允许在评论中使用<sup>...</sup>。所以显然那是2^32,而不是232。 - T.J. Crowder
显示剩余4条评论

6

ECMA-262规范(第15.4节)指出:

如果将属性名P(以字符串形式表示)转换为无符号32位整数后等于P,且P不等于232-1,则P是数组索引。

规范还指出,数组的length属性始终小于232。这似乎排除了4294967295作为数组索引的可能性。


规范的其他相关部分:15.4.2.2、15.4.5.1、15.4.5.2。 - NullUserException
我认为这非常明确。 - Jeff Mercado

0

JavaScript数组可以容纳2^32-1=4294967295个元素。
但是,数组索引从0开始,因此4294967295-1=4294967294


3
0之后是1,那又怎样? - Jeff Mercado
你提到了索引为什么是长度减1,但之前并没有解释为什么长度是2^32-1。这就是你回答中缺失的部分。 - Maple

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接