ES6 Maps and Sets:如何有效地索引对象键?

Posted

技术标签:

【中文标题】ES6 Maps and Sets:如何有效地索引对象键?【英文标题】:ES6 Maps and Sets: how are object keys indexed efficiently? 【发布时间】:2017-11-15 15:57:00 【问题描述】:

在 ES6 中,Maps 和 Sets 可以使用 Objects 作为键。然而,由于 ES6 规范没有规定这些数据结构的底层实现,我想知道现代 JS 引擎如何存储密钥以保证 O(1) 或至少 sublinear 检索?

在像 Java 这样的语言中,程序员可以显式地提供一个(好的)hashCode 方法,该方法将在键空间中均匀地散列键以保证性能。然而,由于 JS 没有这些特性,仍然假设它们在 Maps 和 Sets 实现中使用某种散列仍然公平吗?

任何信息将不胜感激!

【问题讨论】:

是的,他们当然使用散列。而且因为你不能指定你自己的相等性,你也不需要实现你自己的散列函数。他们只是使用对象身份。 es6 Map and Set complexity, v8 implementation 可能重复?如果这回答了你的问题,我会关闭。 啊,我明白了,所以我知道他们使用对象标识来检查是否相等。但是他们如何获得哈希位置呢?某种 memoryAddress % keySpace ? 我不知道,但是是的,这听起来很简单。 【参考方案1】:

是的,该实现基于散列,并且具有(摊销的)恒定访问时间。

“他们使用对象身份”是一种简化;完整的故事是 ES Maps and Sets 使用SameValueZero 算法来确定相等性。

根据本规范,V8 的实现计算字符串和数字的“真实”散列,并选择一个随机数作为对象的“散列”,并将其存储为这些对象的私有(隐藏)属性以供以后访问。 (这不太理想,将来可能会改变,但现在就是这样。)

使用memoryAddress % keySpace 无法工作,因为垃圾收集器会四处移动对象,并且每次任何对象可能已移动时重新散列所有 Map 和 Set 将非常复杂且昂贵。

【讨论】:

嗨,感谢您的解释。我正在搜索 implementationabtion 一段时间,但没有找到。你有什么参考吗? 目前大部分实现在source.chromium.org/chromium/chromium/src/+/master:v8/src/…;寻找例如MapPrototypeSet(在该文件中)用于入口点之一。

以上是关于ES6 Maps and Sets:如何有效地索引对象键?的主要内容,如果未能解决你的问题,请参考以下文章

es6

如何有效地将 google-closure javascript 转换为现代 ES6?

使用Maps与Sets处理集合的交差运算

std::map 可以在迭代器处有效地拆分为两个 std::maps 吗?

如何有条件地导入 ES6 模块?

如何有条件地导入ES6模块?