弱映射如何在ES5中实现?

How can a weak map be implemented in ES5?

another question问了同样的问题,但我无法理解接受的答案。

有问题的库似乎使用 Object.defineProperty 添加对要存储的对象的引用(尽管是间接通过另一个对象)。

但是...肯定意味着对象不能因此而被垃圾回收 link?

我错过了什么?

是否真的可以创建一个对象并将其存储在某处而不维护垃圾收集器注意到的引用? (ES2015 之前)

接受的答案:

It took me a while to grok the code, but then it hit me: the key itself is used to store a reference to the value.

For example, several layers into set it does

defProp(obj, globalID, { value: store }); where defProp has been defined to be Object.defineProperty, obj is the key, globalID is a guid and store is a storage object that contains the value.

Then down in get it looks up the value with

obj[globalID];

This is very clever. The WeakMap doesn't actually contain a reference to anything (weak or otherwise)-- it just sets up a policy of where to secretly store the value. The use of Object.defineProperty means that you won't accidentally discover the value storage-- you have to know the magic guid to look it up.

Since the key directly refers to the value (and the WeakMap doesn't refer to it), when all references to the key are gone, it gets GCed like normal.

The library in question.

surely that would then mean the object cannot be garbage collected because of this link?

是的。

What am I missing?

没有。也许这正是我们想要的行为。

正如答案所解释的那样,“WeakMap 实际上并不包含对任何内容(弱或其他)的引用”和“当所有对钥匙不见了,它像往常一样得到 GC。"

有问题的库中的代码很复杂。但是基于另一个更清晰的 WeakMap 实现,我有以下...

WeakMap 持有一个 弱引用 到键和与之关联的值。这意味着 WeakMap 不会以任何方式影响键对象或值对象的垃圾回收。

在 ES5 中实现此目的的一种方法是将 属性 添加到映射 "added" 时使用的键,然后什么都不做(即做不要将键添加到数组或确实对它做任何事情)。以这种方式,除了它本身之外,没有任何东西指代密钥。

AFAICT WeakMap 有一个有限的 API 因为这个原因。例如,您不能枚举 WeakMap 中的项目,因为它不包含对其内容的引用!

请注意,WeakMap 中的键不能是原始类型(字符串、数字、未定义、空、符号、布尔值)。

当使用 hasget 时,您可以简单地在作为密钥提供的对象上查找秘密 属性。

如果它存在,WeakMap "contains" 或 "has" 它;否则它不会。

对于 get,秘密 属性 可以包含对与键对象关联的值的引用,同样,没有从 WeakMap 到键对象或值对象的引用。

我觉得。