随着 JavaScript 应用程序的复杂性不断增加,内存泄漏越来越成为一个常见的问题。虽然 JavaScript 具有垃圾回收机制,但是在某些情况下,可能会出现一些变量或对象没有被垃圾回收导致内存泄漏的情况。ES2021 引入了 WeakRefs,这是一种新的 JavaScript 引用类型,它提供了解决这些问题的方法。
什么是 WeakRefs
在 Javascript 中,我们可以使用引用类型对变量或对象进行引用。例如:
const obj = { foo: 'bar' };
const arr = [1, 2, 3];
const str = 'hello world';当我们将这些值赋给变量时,变量实际上只是对它们的引用。当没有任何变量引用这些值时,它们将成为垃圾回收的候选对象。
然而,有些情况下,我们需要在变量不再引用某个对象时自动执行某些操作。这时候,如果我们强制使用引用类型,就无法在变量引用计数为 0 的时候自动执行操作。而 WeakRefs 却可以解决这个问题。
WeakRefs 是一种新的 JavaScript 引用类型,它可以在被引用对象被垃圾回收时自动执行回调函数。WeakRefs 可以用来解决一些内存泄漏的问题。
WeakRefs 的原理
WeakRefs 本质上是一种弱引用。在 Javascript 中,通过强引用可以保证一个对象不被垃圾回收,只有当所有引用对象都被删除时,它才会被垃圾回收。而 WeakRefs 的作用是,当强引用被删除时,WeakRefs 会自动 abort 即中断操作,这时候回调函数可以被触发。
为了使用 WeakRefs,我们需要创建一个 WeakRef 对象。当我们创建一个 WeakRef 对象时,它会被关联到一个对象。当这个对象被垃圾回收时,WeakRef 对象会自动被释放,它所关联的回调函数也会自动执行。
const obj = new MyClass(); const weakRef = new WeakRef(obj); // 当 obj 被垃圾回收时,weakRef 回调函数会自动执行。
回调函数的执行方式可以使用某些方法定义。例如,我们可以使用 onnotify 方法:
const obj = new MyClass();
const weakRef = new WeakRef(obj);
weakRef.onnotify = () => {
console.log('对象已被垃圾回收');
}WeakRefs 的应用
WeakRefs 可以应用于一些内存泄漏的场景,例如在采用自定义事件使用的场景。
-- -------------------- ---- -------
----- ------------ -
------------- -
-------------- - --- ------
-
-------- --------- -
-- --------------------------- -
------------------------ ----
-
----- --------- - -------------------------
-------------------------
-
---------- -------- -
----- --------- - -------------------------
-- ------------ -
-------
-
--- ------ -------- -- ---------- -
------------------
-
-
-
----- ------------ - --- ---------------
----- ------- -
------------- -
---------------------- ----------------
-
----------- -
-------------------
-
-
----- --- - --- ----------在上面的代码中,MyClass 实例化时会订阅 EventEmitter 的 foo 事件。如果 MyClass 实例被垃圾回收,但没有取消订阅该事件,则 EventEmitter 中的监听函数池仍然持有 MyClass 实例的引用。当 MyClass 实例和 WeakRefs 结合使用时,我们可以在 MyClass 实例被垃圾回收时自动取消订阅该事件:
-- -------------------- ---- -------
----- ------- -
------------- -
---------------------- ----------------
------------ - --- --------------
-
----------- -
-------------------
-
-
----- --- - --- ----------这样一来,当 MyClass 实例被垃圾回收时,WeakRef 会自动将 handleFoo 函数解除订阅。
除此之外,WeakRefs 还可以用来优化内存占用。例如,在某些场景下,我们需要缓存某些对象,并在一段时间后自动清除这些缓存的对象。使用 Map 对象可以轻松实现这个功能,但是这些缓存的对象永远不会被垃圾回收,也就占用了大量的内存。如果我们使用 WeakRefs 来存储这些缓存对象,则可以让这些对象在不再使用时自动被垃圾回收,从而优化内存占用。
-- -------------------- ---- -------
----- ----- - --- ------
-------- ------------- -
-- ---------------- -
----- ------- - ---------------
----- ----- - ----------------
-- ------- -
------ ------
- ---- -
------------------
-
-
----- ----- - --------------------
----- ------- - --- ---------------
-------------- ---------
------ ------
-在上面的代码中,我们使用了 Map 存储缓存对象,同时使用 WeakRef 关联对象。在 getValue 函数中,当缓存对象过期或被垃圾回收时,WeakRef 自动删除与之相关的缓存对象。
总结
ES2021 中引入了 WeakRefs,通过它我们可以解决一些内存泄漏的问题,可以优化内存占用,使我们的前端应用程序更加高效和稳定。WeakRefs 目前在大多数现代浏览器中得到了支持,是我们在前端开发中不可忽视的一种新的 Javascript 引用类型。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/64c669ae10032fedd38d0dcf