ES12 引入了一项新特性,称为 Weak Refs。这项特性提供了一种弱引用的方式,可用于存储 JavaScript 中的原始类型,例如数字和字符串。
在本文中,我们将深入探讨 Weak Refs 的背后和如何使用它来存储和操作原始类型。
强引用与弱引用
在正式开始之前,让我们首先澄清引用的概念。
在 JavaScript 中,当我们将一个变量分配给另一个变量时,实际上是将一个引用赋值给另一个引用,而不是将实际值赋值给另一个变量。
引用是内存地址的指针,指向存储在计算机内存的实际值。在 JavaScript 中,引用可以分为两种类型:强引用和弱引用。
强引用是指变量对值的生命周期有直接影响。只要变量存在,值就会一直存在,并且 JavaScript 程序将始终拥有对该值的完全控制。
弱引用是指变量对值的生命周期没有直接影响。即使弱引用变量存在,值也可能被垃圾回收器销毁。在 JavaScript 中, WeakRef 对象和 FinalizationRegistry 对象提供了实现弱引用的方法。
Weak Refs 中的原始类型存储
在 JavaScript 中,原始类型存储在堆栈中。堆栈是一段内存区域,局部变量和函数参数都存储在其中。原始类型的值存储在堆栈中,但是 JavaScript 引用并操作这些值的方式会将它们存储在堆中。
由于原始类型在堆栈中占用的空间相对较小,因此通常被视为对内存的轻量级占用。但是,大量原始类型的存储可能会导致内存瓶颈和性能问题。
这时就引入了 Weak Refs。Weak Refs 允许我们使用弱引用来存储原始类型,以减少对堆栈和堆的占用,从而提高性能和减少内存开销。
下面是使用 WeakRef 对象存储数字和字符串的示例代码:
const foo = 42; const bar = "Hello, World!"; const fooRef = new WeakRef(foo); const barRef = new WeakRef(bar); console.log(fooRef.deref()); // 42 console.log(barRef.deref()); // "Hello, World!"
在上面的代码中,我们首先创建了两个原始类型:数字 42
和字符串 "Hello, World!"
。然后使用 WeakRef
对象来创建与之关联的弱引用变量 fooRef
和 barRef
。最后使用 deref()
方法来获取存储在 WeakRef 对象中的值。
在上面的代码中,WeakRef 对象只是一组数字和字符串的标识符。即使我们在使用 WeakRef
对象时删除或更改了它们,值也不会被垃圾回收器自动销毁。我们可以使用 FinalizationRegistry
对象来实现这一点。
下面是使用 FinalizationRegistry
对象和 WeakRef
对象一起存储并自动清除数字和字符串的示例代码:
-- -------------------- ---- ------- ----- --- - --- ----- --- - ------- -------- ----- -------- - --- -------------------------- -- - ------------------ --- ---- ------- ------------ ------- --- ----- ------ - --- ------------- ----- ------ - --- ------------- ------------------------- ----- ------------------------- ----- ---------------------------- -- -- ---------------------------- -- ------- ------- --- - ----- --- - ----- ---------------- -- --------- ---------------------------- -- --------- ---------------------------- -- ---------
在上面的代码中,我们首先创建了数字 42
和字符串 "Hello, World!"
,然后创建一个 FinalizationRegistry
对象,以便在值被回收时执行回调函数。
我们使用 WeakRef
对象创建数字和字符串的弱引用变量,并在注册表中注册它们。然后我们将数字和字符串的变量设置为 null,以触发垃圾回收器清除它们。最后,我们使用 deref()
方法来获取已回收的值。
结论
Weak Refs 为 JavaScript 中的原始类型存储提供了一种灵活而有效的方法。使用 Weak Refs 可以减少对堆栈和堆的占用,从而提高性能和减少内存开销。
有关更多信息,请参见 ECMAScript® 2022 Language Specification。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/66eefbcc6fbf9601972da035