问题描述
如果您查看WeakRef
个polyfill的both个示例中的these,则它们都使用WeakMap
。
但是我不知道这怎么工作。 WeakMap
对其值的引用不强,但对其 keys 的引用却弱。而且这两个polyfill都使用this
作为键。这意味着,如果我说let weakRef = new WeakRef(targetobject)
,那么除非我丢弃targetobject
,否则weakRef
将永远不会收集垃圾。否定了WeakRef
的全部目的,不是吗?
在我有限的实验中,我的理论似乎是正确的。看看这个jsfiddle。
编辑
哦,有人知道起作用的WeakRef
填充吗?
解决方法
这似乎是部分polyfill作者误解的结果,请考虑编写错误报告。
这些方法确实对对象保持了强烈的引用,该实现实际上是一致的,因为程序不能仅仅因为从未观察到删除对象而断定垃圾收集器已损坏。但是,要实现 这项功能要容易得多:只需将对象存储在属性中,根本不用担心WeakMap
。
我认为有些人天真的希望WeakMap
对值的引用很弱,正如您所观察到的那样。在仔细阅读文档之前,我也曾有过这样的误解。不过,这无法解释为什么WeakMap
自2015年以来就成为规范,而WeakRef
却超过3年还没有超过提案阶段。这样的幼稚集合就像Map
中的WeakRefs
,那么为什么语言也不会公开一个?
事实是,用WeakRef
模仿WeakMap
是不可能的(em>不可能的,并且已经进行了仔细的设计以使它如此(主要是不可枚举的)。为什么?尽管完全有可能可靠地实现此行为,但设计团队的想法是确定性和可预测性。 This short paragraph很好地总结了这一点,并提供了推理和一个示例,该示例被认为是错误的过去设计决策。以下两个句子直接排除了诸如WeakRef
之类的 :
这意味着您不应公开任何用作弱引用的API,例如具有的属性在运行垃圾回收后变为null。 JavaScript代码中的对象和数据生存期应该是可预测的。
考虑到这一点,在遵循W3C TAG准则的实现中,不仅不能使用WeakMap
,而且甚至不能使用任何 other 方法(该方法应回答您的最后一个问题) (在评论中),但在狭义的特定情况下可能会使用示例中提到的丑陋且不可靠的漏洞。除非委员会的选择发生根本变化,否则the WeakRef
proposal可能永远不会真正标准化。我们希望,当前版本中包含的措辞谨慎的注意事项以及对过多内存使用以及其他有趣且有充分根据的用例的呼吁最终将允许此类异常。