有效地计算 JavaScript 中对象的键/属性的数量

Posted

技术标签:

【中文标题】有效地计算 JavaScript 中对象的键/属性的数量【英文标题】:Efficiently counting the number of keys / properties of an Object in JavaScript 【发布时间】:2011-12-18 21:13:53 【问题描述】:

这个问题与How to efficiently count the number of keys/properties of an object in javascript?几乎相同。

我想知道一条额外的信息:什么是“恒定时间”确定对象中键数量的方法?我最关心的是在 Node.JS 中执行此操作,因为浏览器上的大多数对象都不会太大而不会引起很大的关注。

编辑: 在 Google Chrome 和 Node.JS 中,Object.keys(obj).length 似乎以线性时间 O(n) 返回(即取决于obj 中的键数)。有没有更好的 O(1) 方法?

我在 Node.JS 中做了一些测试(来源如下)

var tests = [10e3, 10e4, 10e5, 10e6]
for(j in tests) 
    var obj = ;
    for(i = 0; i < tests[j]; i++)
        obj[i] = i;
    console.time('test' + tests[j]);
    Object.keys(obj).length;
    console.timeEnd('test' + tests[j]);

对于 n = 10e3, 10e4, 10e5, 10e6... 结果是:

test10000: 5ms
test100000: 20ms
test1000000: 371ms
test10000000: 4009ms

【问题讨论】:

不。我今天感觉很懒惰......:/星期一的情况,我想。 我怀疑从调用“Object.keys()”的结果中获取“.length”是常数时间,但我也怀疑调用“Object.keys()”是线性的属性的数量。 jsperf.com/object-keys-performance 100 倍于对象中的项目导致它在 Chrome 上的速度是 200 倍。 谢谢,@pimvdb -- 这真是个令人难过的消息。 :( Node.JS 中是否有任何常量时间键计数方法? @BMiner 对不起,我的意思是,Object.keys(o).length 是 O(n)。数组上的.length 是 O(1)。 【参考方案1】:

经过一番研究,没有办法在恒定时间内确定 JavaScript 对象中键的数量,至少在 Node 中没有……而且目前还没有。 Node 内部会跟踪这些信息,但不会公开它,因为在 ECMA-262 5th 中没有这样做的方法。

值得注意的是,Harmony(ECMA 版本 6)可能原生支持 Maps 和 Sets。不确定这些的规格会是什么。

有人告诉我,我们需要向 TC39 委员会提出这个问题。

V8 的错误报告:http://code.google.com/p/v8/issues/detail?id=1800

【讨论】:

【参考方案2】:

ECMA 6 Harmony 引入了 MapSet 类,您可能会使用它们(将来:)

var map = new Map;
map.set('a', 'b');
console.log(map.size); // prints 1

我相信它应该具有 O(1) 的复杂度,但没有尝试过。您可以通过node --harmony script.js 在节点 0.11+ 中运行它。


另一种方法是使用Proxy 类,该类也已添加到harmony中。

【讨论】:

【参考方案3】:

查看源代码,特别是GetLocalElementKeys

v8 objects.cc

【讨论】:

我懒得做这个了。请用英语。我很乐意接受你的回答。 :P 根据对象包含的内容,它们会做不同的事情,最坏的情况似乎是 1 for 循环遍历所有元素。

以上是关于有效地计算 JavaScript 中对象的键/属性的数量的主要内容,如果未能解决你的问题,请参考以下文章

通过 JavaScript 中的键访问对象属性

如何通过值获取 JavaScript 对象中的键?

javascript中window.event事件用法详解

如何将 JavaScript 对象的属性值提取到数组中?

javascript event对象的具体功能是啥

Vue 有效地使用计算属性