为什么ES6的WeakMap不可枚举?

35
在我重新涉足JavaScript(和相关技术)之前,我做了很多ActionScript 3,那里有一个名为Dictionary的对象,它具有像即将推出的WeakMap一样的弱键,但AS3版本仍然像常规通用对象一样可枚举,而WeakMap明确没有.keys().values()
AS3版本允许我们构建一些非常有趣和有用的结构,但我感觉JS版本有些受限。为什么呢?
如果Flash虚拟机可以做到,那么是什么阻止浏览器做同样的事情呢?我读到过这将是“非确定性的”,但这正是重点,对吧?

8
我认为MDN条目已经很好地概括了:由于引用是弱的,因此WeakMap键不可枚举(即没有方法可以给您一个键列表)。 如果它们存在,该列表将取决于垃圾回收的状态,从而引入非确定性。这并不是说不能定义规则,而是通过一开始就不允许这种操作,实现(其中有几个竞争对手)可以完全避开此问题。 - user2864740
当然,这有些合理,但标准委员会有点弱(呵呵),我仍然希望能够了解为什么可枚举性不重要到足以成为必需功能的见解。 - Bartvds
2
@bernstein 不需要。Weak Map 旨在用于缓存实现和类似的情况,其中应用程序的其他部分知道可能在映射中的键。 - Pointy
2
什么?不是的。这不是关于基本Map的问题,而是一个非常具体的Weakmap问题。所提到的项目并没有回答问题,就像其他答案一样,它忽略了AS3版本在非确定性方面运行良好的事实。 - Bartvds
1
@Pointy 事实上,键必须是一个对象而不能是原始数据类型,这使得大多数用例无法使用WeakMap作为缓存。 Web缓存使用URL(字符串),而DAO类使用OID(整数)作为缓存键。 这两种用例都无法使用对象作为键。 - ceving
显示剩余3条评论
2个回答

21

终于找到了真正的答案: http://tc39wiki.calculist.org/es6/weak-map/

弱引用映射(Weak Maps)的一个关键特性是无法枚举它们的键。这是为了防止攻击者观察环境中共享弱引用映射对象的其他系统的内部行为。如果该集合中的项目数量或名称可以从API中发现,即使值不可见,WeakMap实例也可能创建一个之前不存在的侧信道。


1
非常感谢。因此,它是一个误称,应该被命名为SecretKeyAndWeakMap。所有参加过SE 101的人都会哭泣 - bernstein
2
这个答案假设“在共享弱映射对象的环境中” -但这常见吗?-我以前从未听说过。此外,为什么需要这样做?-如果需要,只需创建一个WeakMap实例的专用内部弱指针集合,正如WeakMap对象的名称和定义所建议的那样(它是一个映射集合),因此,如果存在/必须共享,则似乎没有问题,WeakMap实例被实现为创建自己的集合。所以我还没有看到这个答案的原因。 - Destiny Architect
17
这令人失望。无法列举出弱集合的元素,使其实用性受到了限制。 - Brandon
5
我认为这并不是实际情况。我认为这更多是关于能够观察垃圾回收的问题。如果你允许枚举WeakMaps,那么你就会让开发者面临一种不确定性形式,因为他们现在可以观察垃圾回收和内存,而目前他们无法观察。 - Benjamin Gruenbaum
1
看起来 JavaScript 将来会终于获得一个真正的 WeakReference 实现!https://dev59.com/gnVC5IYBdhLWcg3whRgw#58009243这将通过结合两个方面实现可迭代的 WeakMap。(为 WeakMap 的每个键创建一个 WeakRefs 数组,然后通过迭代键并将其与 WeakMap 中对应的值相结合来进行迭代。) - Venryx
Firefox Nightly已经添加了对WeakRef的实验性支持。以下是一个使用它创建WeakSet可迭代版本的示例实现:https://gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d。链接的规范还包括WeakMap的实现。 - seanlinsley

0

这是一个权衡。如果你引入支持枚举的对象<->对象字典,你有两个选项与垃圾回收相关:

  1. 将键条目视为强引用,防止被用作键的对象被垃圾回收。

  2. 将其作为弱引用,允许在其他引用已经不存在时回收其键。

如果你选择方案#1,那么很容易使自己在内存中泄漏大量对象。另一方面,如果你采用方案#2,则键字典将取决于应用程序中垃圾回收的状态,这将不可避免地导致难以跟踪的错误。


6
如OP和其他评论中所述,AS3具有仍可枚举的弱键。它可以正常工作,并允许收集/关联值而不会阻塞垃圾回收。然后,您可以循环遍历这些尚未被收集的键来处理与其相关的内容。 - Bartvds
1
这是非确定性行为,也就是我解释的情况#2,并且会产生你在另一个回答中描述的侧信道。 - user3550896

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