为什么索引号非常高的javascript数组会导致崩溃/减速/故障?

为什么索引号非常高的javascript数组会导致崩溃/减速/故障?,javascript,node.js,express,Javascript,Node.js,Express,基本上,破坏我的node js express服务器的代码如下: resultArr = []; resultArr["test"] = []; resultArr["test"][2015073012] = someObject; 当我把这个改成这个时,它运行起来没有问题 resultArr = []; resultArr["test"] = {}; resultArr["test"][2015073012] = someObject; 我是这样循环工作的 为什么它会破坏我的应用程序?正如

基本上,破坏我的node js express服务器的代码如下:

resultArr = [];
resultArr["test"] = [];
resultArr["test"][2015073012] = someObject;
当我把这个改成这个时,它运行起来没有问题

resultArr = [];
resultArr["test"] = {};
resultArr["test"][2015073012] = someObject;
我是这样循环工作的


为什么它会破坏我的应用程序?

正如您所发现的,您不应该为此使用数组,而应该使用对象。但您应该更进一步,在顶层也使用对象。由于您的
2015073012
值将用作字符串,因此最好从一开始就将其设置为一个字符串:

var results = {};
results.test = {};
results.test['2015073012'] = someObject;
或:

现在,在任何JavaScript引擎中都不会有任何问题

(顺便说一句,我将名称从
resultar
更改为
results
,因此名称听起来不像是数组。)

JavaScript数组适用于具有连续项的情况,如
array[0]
array[1]
array[2]
,等等。当键具有任意字符串或任意大的数字时,不要使用数组,而是使用对象

不要被其他语言(如PHP)所迷惑,它们有一个单一的
数组
类型,既可以作为顺序
0,1,2,3,…
数组,也可以作为键值对的字典。JavaScript既有数组也有对象:对于顺序大小写使用数组,对于键值大小写使用对象

回到你的问题,为什么这个代码会被破坏:

resultArr = [];
resultArr["test"] = [];
resultArr["test"][2015073012] = someObject;
一种可能的解释是,当您为
[2015073012]
数组索引赋值时,JavaScript引擎正在执行您告诉它的操作:它创建一个包含2015073013项的数组(比您给出的值多一个,因为数组索引从0开始)。这在你的数组中超过20亿个条目!你可能会发现这会导致一个问题,而这肯定不是你想要的

其他引擎可能会意识到这是一个荒谬的大数字,并将其视为字符串而不是数字,就好像您首先使用的是对象而不是数组一样。(JavaScript数组也是一个对象,可以有键值对和数字索引。)

事实上,我在最新版本的Chrome中,在JavaScript控制台中交叉手指尝试了这一点,但没有出现任何问题:

a = [];
a[2015073012] = {};

但你没有那么幸运。无论如何,在这种情况下,您应该始终使用对象而不是数组,以确保它们被视为键值对,而不是创建包含大部分空元素的巨大数组。

这取决于特定的JS实现(本例中为V8)。我很惊讶它导致了它的“崩溃”,因为我认为它是作为稀疏数组实现构建的,或者转换为稀疏数组实现的(因为它的索引超过了~105k)。如果它确实导致它“崩溃”,那么我的第一个预感是它仍在尝试使用密集阵列实现。。或者是其他地方出了问题。你能展示更多的代码吗?根据ES5,数组的最大长度是2^32-1,但是如果数组中有很多元素,那么它就会变慢,直到内存不足为止。@kenticny这不完全正确。现代JS引擎有几种不同的数组实现——最显著的是:一种由连续分配支持的“密集”数组,一种更像普通对象的“稀疏”数组,并且可以在它们之间切换;行为和条件完全依赖于实现。在这种情况下,V8为什么没有做到这一点是个问题。。如果某个地方有bug报告,我不会感到惊讶。@user2864740-感谢上面有趣且内容丰富的评论,以及(现在已删除)在我写答案时让我保持警觉的评论。:-)你对这次讨论做出了很大贡献。
a = [];
a[2015073012] = {};