我想通过一个真实的简单的示例和在何处使用它们来了解ES2021中的WeakRef
和终结器是什么。
我知道,WeakRef
是一个类,这将允许开发人员创建对对象的弱引用,而终结器或FinalizationRegistry
允许您注册回调函数,当对象被垃圾收集时将调用这些函数
const myWeakRef = new WeakRef({
name: 'Cache',
size: 'unlimited'
})
// Log the value of "myWeakRef":
console.log(myWeakRef.deref())
2条答案
按热度按时间wfsdck301#
一如既往,MDN's docs help。
WeakRef对象包含对对象的弱引用,称为其目标或referent。对对象的弱引用是不阻止对象被垃圾收集器回收的引用。相比之下,正常的(或强)引用将对象保留在内存中。当对象不再有任何对它的强引用时,JavaScript引擎的垃圾收集器可能会销毁对象并回收其内存。如果发生这种情况,您将无法再从弱引用中获取对象。
在JS的几乎所有其他部分,如果某个对象(A)持有对另一个对象(B)的引用,B将不会被垃圾收集,直到A也可以被完全垃圾收集。例如:
在这种情况下,
theB
将 * 永远 * 不会被垃圾收集(除非theA.obj
被重新分配),因为顶层的theA
包含一个属性,该属性持有对theB
的引用;它是一个强引用,防止垃圾回收。另一方面,WeakRef提供了一个可以访问对象的 Package 器,同时不会阻止该对象的垃圾收集。在WeakRef上调用
deref()
将返回对象 * 如果它还没有被垃圾收集 *。如果它已经被GC'd,.deref()
将返回undefined
。FinalizationRegistry处理类似的问题:
FinalizationRegistry对象允许您在对象被垃圾回收时请求回调。
首先定义注册表和要运行的回调函数,然后在注册表上调用要观察的对象
.register
。这将让您知道 * 确切的时间 * 某些内容被垃圾收集。例如,以下内容将在obj
被回收后记录Just got GCd!
:您还可以在调用
.register
时传递一个值,该值在收集对象时传递给回调。一个二个一个一个
将记录
the object named "obj"
,它将被GC'd。所有这一切都表明,对这些工具的需求很少。正如MDN所说:
正确使用FinalizationRegistry需要仔细考虑,如果可能的话,最好避免使用。避免依赖规范未保证的任何特定行为也很重要。何时,如何以及是否发生垃圾收集取决于任何给定JavaScript引擎的实现。您在一个引擎中观察到的任何行为在另一个引擎中可能不同,在同一引擎的另一个版本中,垃圾收集是一个很难解决的问题,JavaScript引擎的实现者们一直在不断地完善和改进他们的解决方案。
最好是让引擎本身尽可能地自动处理垃圾收集,除非您有非常好的理由自己关心它。
htzpubme2#
弱引用的主要用途是实现对大型对象的缓存或Map。在许多情况下,我们不想长时间保留大量内存来保存这些很少使用的缓存或Map。我们可以允许内存很快被垃圾收集,如果我们再次需要它,我们可以生成一个新的缓存。如果变量不再可访问,JavaScript垃圾收集器会自动删除它。
当执行上面的代码时,它会在2秒后打印“Hello world”。基于我们如何使用callback()函数,aBigObj可能会永远存储在内存中。
让我们将aBigObj设为弱引用。
第一个setTimeout()肯定会打印名称的值。这在创建弱引用后的第一轮事件循环中得到保证。
但是不能保证第二个setTimeout()会打印“Backbencher”。它可能已经被垃圾收集器清除了。由于垃圾收集在不同的浏览器中工作方式不同,我们不能保证输出。这也是为什么我们在该高速缓存等情况下使用WeakRef。
**一个