【问题标题】:How can a weak map be implemented in ES5?如何在 ES5 中实现弱映射?
【发布时间】:2017-11-07 11:05:09
【问题描述】:

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

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

但是……这肯定意味着对象不能因为这个链接而被垃圾回收吗?

我错过了什么?

真的有可能创建一个对象并将其存储在某个地方而无需维护垃圾收集器注意到的引用吗? (在 ES2015 之前)

接受的答案:

我花了一些时间来摸索代码,但后来它击中了我:关键 本身用于存储对值的引用。

例如,设置好几层就可以了

defProp(obj, globalID, { value: store }); defProp 在哪里 定义为 Object.defineProperty,obj 是 key,globalID 是 guid 和 store 是一个包含值的存储对象。

然后在 get 中查找它的值

obj[globalID];

这很聪明。 WeakMap 实际上并不包含引用 任何东西(弱或其他)——它只是建立了一个政策 秘密存储价值。 Object.defineProperty 的使用意味着 你不会意外发现价值存储——你必须知道 魔法向导来查找它。

由于键直接引用值(而 WeakMap 没有 参考它),当所有对密钥的引用都消失时,它会被 GCed 像平常一样。

The library in question.

【问题讨论】:

  • 当然是key引用了value,不然查不到。在键被回收之前,不会对值进行垃圾收集。弱映射的要点是 map 对象 没有对键或值的引用。

标签: javascript weakmap


【解决方案1】:

相关库中的代码令人费解。但是基于另一个更清晰的 WeakMap 实现,我有以下...

WeakMap 拥有对与其关联的键和值的弱引用。这意味着 WeakMap 不会以任何方式影响键对象或值对象的垃圾收集。

在 ES5 中实现这一点的方法是在键被“添加”到地图时添加一个(如果需要,可以隐藏)属性,然后什么都不做(即不要将键添加到数组或确实可以用它做任何事情)。这样一来,除了它自己之外,没有任何东西涉及到密钥。

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

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

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

如果它存在,WeakMap“包含”或“拥有”它;否则它不会。

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

我认为。

【讨论】:

  • WeakMap 也没有强引用该值。对整个键值对的引用很弱。
【解决方案2】:

当然这意味着该对象不能因为这个链接而被垃圾回收?

是的。

我错过了什么?

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

正如答案所解释的,“WeakMap 实际上并不包含对任何东西(弱或其他)的引用”和“当对密钥的所有引用都消失时,它会被 GCed像平常一样。"

【讨论】:

  • ...但是用于存储值的任何数据结构都维护一个链接。如果对象永远不会被 GC 处理,那么这不是很“弱”吗?
  • 我不确定您的期望。允许观察 GC 的不是弱引用。 WeakMap 中的“弱”只是关于从映射到键和值的链接。
  • 在 ES2015 WeakMap 中,我可以向其中添加一个对象,取消对该对象的所有其他引用,并且该对象将有资格进行 GC。在这个库中,我可以将一个对象添加到它的“弱映射”并取消对该对象的所有引用,并且在我深入研究该库用于存储对象的数据结构并取消那里的引用之前,它不会被 GC 处理。从而否定了图书馆的观点。我确定我错过了什么。
  • @BenAston 是的,看来您还没有完全理解库设计。 “key直接引用value,WeakMap不引用”。地图内部没有“图书馆使用的数据结构”。
猜你喜欢
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-14
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多