在javascript中有没有办法为另一个对象创建“弱引用”? Here is the wiki page describing what a weak reference is. Here is another article that describes them in Java.任何人都可以想到在javascript中实现此行为的方法吗?
答案 0 :(得分:36)
JavaScript中的weakrefs没有语言支持。您可以使用手动引用计数自行滚动,但不是特别顺畅。您无法创建代理包装器对象,因为在JavaScript对象中永远不知道它们何时会被垃圾收集。
所以你的'弱引用'在一个简单的查找中成为一个键(例如整数),带有add-reference和remove-reference方法,当没有手动跟踪的引用时,可以删除条目,将来查找该键以返回null。
这不是一个真正的弱点,但它可以解决一些相同的问题。它通常在复杂的Web应用程序中完成,以防止在DOM节点或事件处理程序与与之关联的对象(如闭包)之间存在引用循环时,浏览器(通常是IE,尤其是旧版本)的内存泄漏。在这些情况下,甚至可能不需要完整的参考计数方案。
答案 1 :(得分:14)
在NodeJS上运行JS时,您可以考虑https://github.com/TooTallNate/node-weak。
答案 2 :(得分:3)
真正的弱引用,不,还没有(但浏览器制造商正在研究这个主题)。但是这里有一个关于如何模拟弱引用的想法。
您可以构建一个可以驱动对象的缓存。存储对象时,缓存会预测对象将占用多少内存。对于某些项目,例如存储图像,这很容易解决。对于其他人来说,这将更加困难。
当您需要一个对象时,然后向缓存询问它。如果缓存具有该对象,则返回该对象。如果不存在,则生成,存储然后返回该项目。
当预测内存的总量达到一定水平时,通过缓存删除项来模拟弱引用。它将根据检索的频率来预测最少使用哪些项目,并根据它们被取出的时间加权。如果创建项的代码作为闭包传递到缓存中,也可以添加“计算”成本。这将允许缓存保留构建或生成非常昂贵的项目。
删除算法很关键,因为如果你弄错了,那么你最终可能会删除最受欢迎的项目。这会导致糟糕的表现。
只要缓存是唯一具有永久引用存储对象的对象,那么上述系统应该可以很好地替代真正的弱引用。
答案 3 :(得分:3)
2021 年更新
WeakRef
现在已在 Chrome、Edge 和 Firefox 中实现。仍在等待 Safari 和其他一些支持。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
2021 年 5 月更新 它现在可以在 Safari 上使用,因此所有主要浏览器都可以使用它。见上文。
答案 4 :(得分:2)
仅供参考; JavaScript没有它,但ActionScript 3(也是ECMAScript)也可以。查看constructor parameter for Dictionary。
答案 5 :(得分:2)
尚不能使用弱引用,但很可能很快就可以使用,因为JavaScript中的 WeakRefs 正在开发中。详细信息如下。
现在在第3阶段中的提案,这意味着它已经完成了specification,并且进一步的完善将需要实现和用户的反馈。
WeakRef 提案包含两个主要的新功能:
弱引用的主要用途是用于实现保存大型对象的缓存或映射,在这种情况下,希望大对象不要仅因为它出现在缓存或映射中而保持活动状态。
完成是要执行的代码,以在程序执行无法访问的对象之后清除。用户定义的终结器启用了几个新的用例,并可以在管理垃圾收集器不知道的资源时帮助防止内存泄漏。
https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references
答案 6 :(得分:1)
使用缓存机制模拟弱引用,如JL235建议的above,是合理的。如果本地存在弱引用,您会观察到这样的行为:
this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not
使用缓存,您会观察到:
this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts
作为参考的持有者,你不应该对它何时引用一个值做任何假设,这与使用缓存没什么不同
答案 7 :(得分:1)
最后他们在这里。尚未在浏览器中实现,但很快就会实现。
答案 8 :(得分:-3)
EcmaScript 6(ES Harmony)有一个WeakMap对象。现代浏览器中的浏览器支持是pretty good(Firefox的最后3个版本,chrome甚至即将推出的IE版本都支持它)。
答案 9 :(得分:-4)
http://www.jibbering.com/faq/faq_notes/closures.html
ECMAScript使用自动垃圾收集。规范没有定义细节,而是将其留给实施者进行整理,并且已知一些实现对其垃圾收集操作给予非常低的优先级。但是一般的想法是,如果一个对象变得不可接受(通过没有剩余的引用可供执行代码访问),它就可用于垃圾收集,并且在将来的某个时刻将被销毁,并且它正在消耗的任何资源被释放并返回到系统重复使用。
退出执行上下文时通常会出现这种情况。范围链结构,Activation / Variable对象以及在执行上下文中创建的任何对象(包括函数对象)将不再可访问,因此可用于垃圾回收。
意味着没有弱者只有那些不再可用的。