为什么WeakMaps不可迭代?

3
现在,Javascript有称为WeakMapWeakSet的类,其中键是弱引用。为什么这些实例不能被迭代,即不能使用WeakMap#entries进行迭代?请注意:这不是重复的问题。另一个问题问“如何”,而这个问题问“为什么”。

@bergi 这个问题不是重复的。你链接的那个问题问“如何”,而我的问题问“为什么”-请注意,链接问题的答案没有解释“为什么”。 - Lucien
你使用弱引用结构,不想让这些对象保持活动状态,即使它们在集合中仍然存活,但你并不关心它们是否存活。迭代意味着你关心它们是否存活,这里存在一种自然的紧张关系。同时允许两者可能会导致错误的产生。 - arnt
@Lolums 抱歉,链接不正确。这个更加合适。 - Bergi
2个回答

5

MDN解释如下:

如果是这样的话,列表将取决于垃圾回收的状态,引入不确定性。

但您可能想知道这到底意味着什么。

首先,垃圾回收是不确定的。JavaScript程序可能会被垃圾回收器在运行环境自行决定的情况下进行垃圾回收。

现在想象一下我们有以下程序:

const weakMap = new WeakMap();

const key1 = { data: 123 };
weakMap.set(key1, "value");
weakMap.set({ data: 456 }, "value");

for (const [key, value] of weakMap) {  // This does not actually work, of course
  console.log(`${key} is ${value}`);
}

您期望这个程序会产生什么结果?

我们无法确定,因为实际上由{ data:456 }创建的对象只会在我们的映射中被引用。因此,该条目将被垃圾回收器删除。但是我们不能确定(甚至有点不太可能),当迭代它时,垃圾回收器已经从地图中删除了它。另一方面,它确实可能已经删除了它。

该程序将表现出不可预测的行为,因此不允许使用。


看起来JavaScript将来终于会得到一个真正的WeakReference实现!https://dev59.com/gnVC5IYBdhLWcg3whRgw#58009243这将通过结合两者来启用可迭代的WeakMap。(为每个WeakMap键创建一个WeakRefs数组,然后通过迭代键并将其与WeakMap值组合来进行迭代) - Venryx
"您期望此程序会产生什么结果?" - 我期望在循环中会有对现有对象的“键”和“值”的强引用,以便我可以管理它们。 - rick-rick-rick
@rick-rick-rick 当然可以,但是垃圾回收可能会在你的for循环之前运行。 - idmean

0
根据文档

与Map对象的一个不同之处在于,WeakMap键不可枚举(即没有方法可以给您提供键列表)。如果它们是这样的话,列表将取决于垃圾回收的状态,引入了非确定性。

此外,WeakMap#entries会创建对对象的额外引用,从而防止垃圾回收并破坏WeakMap的目的。


这些额外的引用不能是弱引用吗? - Lucien

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