JavaScript对象中的属性数量是否有限制?

24
我们有一个拥有超过75000个属性的对象。该对象的格式如下所示:
// The key starts with 3 letters and then is followed by 8 numbers
var bigArray = {'AAA########':123456789,
                'AAA########':123456790,
                'AAA########':123456791
               }; 

JavaScript对象的属性数量是否有已知限制? 根据我的测试,该对象在65500个元素时仍能正常工作。

  • 在Windows 7上,使用IE9运行脚本会崩溃(错误代码-2147024882)。
  • 而在Windows XP上,使用IE8则可以正常运行。

1
你有什么问题吗? - talnicolas
65535(双字节整数的最大值)似乎是一个安全的假设。http://en.wikipedia.org/wiki/65535_(number) - Tobias Beuving
6个回答

20
在当前版本的Chrome(2017年9月),我只能使用约830万个键。尝试将此粘贴到您的浏览器控制台中:
let obj = {};
let keyCount = 0;
while(1) {
  obj[Math.random()] = Math.random();
  if(++keyCount % 10000 === 0) console.log(keyCount);
}

我在Node.js中得到了一个相同的限制:

node --max-old-space-size=20000 -e "let obj = {}; let keyCount = 0; while(1) { obj[Math.random()] = Math.random(); if(++keyCount % 10000 === 0) console.log(keyCount); }"

有趣的是,如果我使用Map,在它崩溃之前我可以获得大约1680万个键(你可以通过类似this的东西来突破这个限制)。

3
现在是2020年,我也获得了大约830万。 - The Qodesmith
对于 Map,1680 万的限制基本上可能是 2^24 的限制 https://bugs.chromium.org/p/v8/issues/detail?id=11852,而对于 Object,830 万可能是对象上的 2^23(在这种情况下,它似乎更容易挂起而不是产生特定的错误消息)。 - Colin D
使用您的浏览器控制台代码时,我的限制是1600万,但当我使用整数键时,它变成了2.852亿。当我使用bigint键时,它变成了2.32亿,这让我感到惊讶,因为我认为键在添加为属性名称之前会被转换为字符串。看来不是这样。 - PHP Guru
这是否意味着每个嵌套对象也可以拥有一千六百八十万个键? - inux
这是否意味着每个嵌套对象也可以有1600万个键? - undefined

9

我不确定实际值是多少,但我在使用node.js时(在一台带有16 GB内存的Mac上)看到了实际的上限约为400,000。

这里是我从数据库中将行添加到对象的日志:

[[21:32:34.325]] [LOG] 340001, pint of delight
[[21:32:35.574]] [LOG] 350001, pound shrimp
[[21:32:36.545]] [LOG] 360001, ravioli allaragosta
[[21:32:37.721]] [LOG] 370001, roasted ham and cheese
[[21:32:39.862]] [LOG] 380001, salmon kama
[[21:32:41.152]] [LOG] 390001, scallops and vegetables
[[21:32:42.150]] [LOG] 400001, show cabernet ca
[[21:32:44.412]] [LOG] 410001, sloppy nachos
[[21:33:25.425]] [LOG] 420001, spaghetti or ziti sauce
[[21:35:37.839]] [LOG] 430001, steak au poivre vert
[[21:37:37.202]] [LOG] 440001, sushi moriawase
[[21:39:45.365]] [LOG] 450001, tequila shooters
[[21:42:09.036]] [LOG] 460001, toro roll with scallion
[[21:44:32.796]] [LOG] 470001, two enchiladas taco rice and refried beans
[[21:47:02.584]] [LOG] 480001, veuve clicquot ponsardin rose reims nv
[[21:49:04.020]] [LOG] 490001, whole turkey gourmet sides
[[21:51:15.264]] [LOG] finished

在大约 400,000 条记录之前,插入 10,000 条新记录需要约 1 秒钟。超过 410,000 条时,时间增长几乎呈指数增长。

我不确定该如何解决这个问题。也许可以创建两个对象,每个对象限制为 400,000 个键... 这可能有点费力,但比重写字典对象要好 :)

更新: 看起来实际上是使用的内存量成了问题,而不仅仅是对象数量。我的计算机在使用约 1.5 GB 的 RAM 时变得非常缓慢。这可能与分配给 node.js 进程的内存有关,可以通过此参数增加:--max_old_space_size=4096(数字以 MB 为单位)。


你知道4GB是针对所有NodeJS安装还是仅取决于你自己的计算机吗? - Kyle Hotchkiss
不确定,但我总共有16GB的RAM - 你可以调整--max_old_space_size参数; 真是个奇怪的名字...! - Nico

5
由于Javascript的内存限制,数组的最大限制是2^32 - 1或4294967295。请参考链接

4
OP 没有使用数组,他只是声明了一个单独的大对象。 - Justin Niessner
2
我猜JavaScript的内存会限制所有类型,是吗? - talnicolas

5

根据我们对此问题的测试,似乎IE9和Windows 7将HTA脚本中的行数限制为65535。我没有在任何来源中找到有关此问题的信息,这只是我们测试的结果。


4

这将是2^32 -1; 然而,特定的浏览器可能会进行进一步的限制。


2

在Windows 10上,我使用16GB RAM的电脑,并测试了Deno 1.6.2版本。

Javascript对象最大键数为116,597,277

deno eval "let obj = {}; let keyCount = 0; while(1) { ++keyCount; obj[keyCount] = keyCount; if(keyCount % 10000 === 0 || keyCount > 116590000) console.log(keyCount); }"

地图最大键数:116,597,277

deno eval "let obj = new Map(); let keyCount = 0; while(1) { ++keyCount; obj[keyCount] = keyCount; if(keyCount % 10000 === 0 || keyCount > 116590000) console.log(keyCount); }"

我在使用Edge版本87.0.664.66和Chrome版本87.0.4280.88测试Javascript对象和Map时得到了相同的数字。


1
我认为你在这里看到的是一种幕后优化,因为你正在使用连续整数作为键。如果你使用随机键,你仍然会得到截至2021年3月的更低的830万限制(在Deno、Node和Chromium中进行了测试)。 - joe
2
@joe 你说得对,只需将字符串添加到键中(将 obj[keyCount] = keyCount; 更改为 obj['a'+keyCount] = keyCount;)即可获得相同的结果,即 830 万(代码只是停止工作,不会因整数键而退出异常)。 - Stefano Spinucci
请参阅此处的Chrome/Node.js/V8相关问题:https://bugs.chromium.org/p/v8/issues/detail?id=11852 - Colin D

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