JavaScript中,对于随机查找,Map是否比Object慢?

7
考虑以下两个片段(来自这个jsperf条目):
let val = 0;
for(let i of indices) {
  val += map.get(i);
}
// ---
let val = 0;
for(let i of indices) {
  val += obj[i];
}

这里,map 是一个 Mapobj 是一个普通的 JavaScript 对象(let obj = {}) ,indices 是一个随机索引的数组。这两个对象都已经预先填充了数据,以便查找实际返回数据。查看 jsperf 获取完整代码。
问题:
为什么普通的 JavaScript 对象的表现要比Map快 5 倍以上?这仅仅是因为截至目前,Map 还很新,没有被优化吗?或者在Map查找中存在一些开销,这将使它永远无法像 POJO 那样快?
如果只是还没有被优化,我们可以期望它最终对于随机查找会比 POJO 更快吗?为什么?为什么不?

1
我怀疑这是由于方法调用开销所致。此外,您滥用集合作为数组,仅存储整数索引。对于超级优化的属性访问来说,尝试使用某种类型的键。 - Bergi
@Bergi修复了数组(尽管需要明确的是,它与此问题无关),谢谢。这个问题所涉及到的比较是POJO与Map查找速度。您是否在说Map可能没有针对整数索引进行优化,而POJO有?还是这只是一个旁思,您是在说这很可能是由于方法调用开销造成的? - user993683
2
我猜这两种情况都有可能。你也可以尝试通过执行 obj = {get(p) { return this[p]; }}; 并调用 obj.get(i) 来模拟开销,但是微基准测试很容易欺骗我们 - Bergi
一开始没有看到你的编辑。尝试使用字符串键并添加了伟大的obj.get(i)建议,看起来你是对的!https://jsperf.com/map-vs-pojo-lookups 所以最初的难题是POJO在底层针对整数进行了优化(基本上被转换为数组),以及方法调用开销。随意发布一个带有指向该jsperf的链接的答案。感谢你的帮助! - user993683
1个回答

8

感谢 @Bergi 提供的答案。

普通的 JavaScript 对象在初始 jsperf 中表现得如此出色的原因是,JS 引擎可以看到我们使用对象就像一个数组(连续的整数键),因此它“假定”它是一个数组,并可以基于此进行许多优化。这对于 Map 并非如此。

但是,Map 还有进一步的劣势,即它需要一个方法调用(map.get(p)),而不是直接属性查找(obj[p])。这已经被证明无法被优化,如此 jsperf 所示:http://jsperf.com/map-vs-pojo-lookups


5
链接已失效。 - ZzZombo
1
@ZzZombo和用户也是;/ - Vencovsky

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