EcmaScript5 中的 WeakMap 实现?

Posted

技术标签:

【中文标题】EcmaScript5 中的 WeakMap 实现?【英文标题】:WeakMap implementation in EcmaScript5? 【发布时间】:2013-04-28 06:36:48 【问题描述】:

我遇到了一个在 ES5 中实现跨浏览器 WeakMap 的 javascript library。 (WeakMap 计划用于 ES6。)

如果没有 JavaScript 语言本身的支持,这怎么可能工作?

编辑:为了清楚起见,我指的是Weak地图,而不是常规地图。我使用 Chrome 的分析器测试了这个项目,并且密钥不是由强引用持有的。他们无需从 WeakMap 中删除即可获得 GC。

【问题讨论】:

考虑研究源码。 @squint 它正在做一些相当深入的事情——我无法弄清楚它是如何没有对键进行强引用的。例如,它不使用数组。 WeakMaps 是一个 ES6 功能,它允许您将数据与对象相关联,但当对象或 WeakMap 实例本身被垃圾收集时,仍然让该数据被垃圾收集。如果没有语言支持,就不可能做到这两点。大多数 WeakMap 垫片忽略了当 WeakMap 实例本身被 GC 时让数据被 GC 的部分。 【参考方案1】:

我花了一些时间来摸索代码,但后来我突然想到了:键本身用于存储对值的引用。

例如,将几层放入set 就可以了

defProp(obj, globalID,  value: store );

其中defProp 已定义为Object.definePropertyobj 是键,globalID 是 guid,store 是包含值的存储对象。

然后在get 中查找值

obj[globalID];

这很聪明。 WeakMap 实际上并不包含对任何东西(弱或其他)的引用——它只是设置了一个秘密存储值的策略。使用Object.defineProperty 意味着您不会意外发现值存储——您必须知道魔法指南才能查找它。

由于键直接引用值(而 WeakMap 不引用它),当所有对键的引用都消失时,它会像往常一样被 GC。

【讨论】:

如果obj是WeakMap键,globalID是在obj上定义的,我想知道为什么globalID在使用Object.getOwnPropertyNames()时没有出现。 我也有同样的疑惑;太糟糕了,lib 远远落后于它自己,以至于几乎无法阅读。必须有一个更简单的解释...... 想通了:lib 作弊:它重新定义了 Object.getOwnPropertyNames()。 boo 用于踩踏现有的原生函数。 它只重新定义 getOwnPropertyNames 以实现 WeakMap。它不会破坏任何东西,并且getOwnPropertyNames' 功能保持不变。该环境与 ES5 完全向后兼容,并与 ES6 WeakMaps 完全向前兼容。这真是个好主意。我在Secrets 中使用它达到了同样的效果。 垫片不提供 WeakMap 的主要属性之一:该值被弱保存。这个 shim 在键和值之间创建了一个强引用......类似于将值设置为键对象的属性。

以上是关于EcmaScript5 中的 WeakMap 实现?的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的WeakMap和WeakSet

JavaScript 中的 Map, Set, WeakMap, WeakSet

对象和数组的 ECMAScript5 深拷贝

10-map/WeakMap/WeakSet的使用场景

javascript新增加的数据结构: Set Map WeakSet WeakMap

JavaScript WeakMap