随着时间的推移,前端技术也在不断发展。在 ECMAScript 2021 中,新增了 WeakRef 和 FinalizationRegistry 这两个 API,它们能够帮助我们更好地管理内存,防止内存泄漏问题,本文将详细介绍这两个 API 的使用,并给出实际示例代码。
WeakRef
在介绍 WeakRef 之前,我们先来了解一下 JavaScript 中的内存管理机制。当我们创建一个对象时,它将被分配在内存中。当我们不需要它时,JavaScript 垃圾回收机制会检测它是否已经变成垃圾(即无法再被引用),然后将其从内存中释放,以便其他对象可以重用该内存。
在某些情况下,我们希望在对象不再被使用时自动将其从内存中释放,而不是等待垃圾回收器。WeakRef 提供了这种功能。WeakRef 实例是对另一个对象的弱引用,这意味着它不会防止该对象被垃圾回收器回收,因为垃圾回收器不会将弱引用的对象视为被引用的对象之一。
WeakRef 例子:
class MyClass {} const obj = new MyClass(); const ref = new WeakRef(obj); console.log(ref.deref() === obj); // true
上面的代码创建了一个 MyClass 的实例,然后创建了一个 WeakRef 对象 ref
。我们可以通过 deref
方法获取弱引用对象,如果弱引用对象是可用的,那么 deref
返回弱引用对象的实例,否则返回 undefined
。
WeakRef 对象对于临时对象(例如缓存中的对象)非常有用,这些对象可以在当前执行环境不再需要它们时被释放。
FinalizationRegistry
FinalizationRegistry 对象允许我们在对象被垃圾回收时执行回调函数。类似于 WeakRef,FinalizationRegistry 对象不会阻止垃圾回收器回收对象,但会在对象遭受垃圾回收时执行回调函数。
FinalizationRegistry 例子:
-- -------------------- ---- ------- ----- ------- - ------------- - -------------- - ----------------------- -- -- - ------------------- -- ----- ----------- --- - - ----- -------- - --- ------------------------------ -- - --------------------- ------------ --- ----- --- - --- ----------
上面的代码注册了一个 FinalizationRegistry 对象,在 MyClass 的构造函数中注册了一个回调函数,在对象被垃圾回收时执行这个回调函数。我们可以通过 heldValue
参数获取对象的实例。
如何使用
我们通过一个例子来演示如何使用 WeakRef 与 FinalizationRegistry 来避免内存泄漏。
我们有一个对象数组 objs
,每次我们想要将一个对象添加到数组中时,我们可以使用生成的 UUID 作为它的键,并将 WeakRef 对象作为值。创建一个 FinalizationRegistry 对象来跟踪对象的回收。如果对象被垃圾回收了,FinalizationRegistry 将会执行一个回调函数,清理数组 objs
中的对应项。
-- -------------------- ---- ------- ----- ---- - --- ----- -------- - --- ------------------------- -- - ----- ----- - ------------------ -- -------- --- ------ -- ------ --- --- - ------------------ --- - --- -------- -------------- - ----- ---- - --------------- ---------------- ---- --- --------------- ---------------------- ------ - -------- -------------- - -- -- ---- -- - -- -------- ---------------- ------------ ---------------- ------------ ---------------- ------------ -- ---- ------- - -----
上面的代码将对象 obj
保存在一个数组中,并通过 WeakRef 的方式保存引用对象。而且通过 FinalizationRegistry 对象来跟踪它们的回收。当我们的数组 objs
中的某个对象变成垃圾时,对应的回调函数会将其从数组中删除。这样,我们就可以避免内存泄漏的问题。
结论
使用新的 WeakRef 和 FinalizationRegistry API,我们可以更好地管理内存,防止内存泄漏问题。在编写 JavaScript 代码时,我们应该始终注意内存使用,并尽可能地避免不必要的对象引用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/673319670bc820c582408547