ES2021:引用不足:WeakRefs&FinalizationRegistry对象

62 阅读2分钟

一般来说,在JS中,对象的引用是强引用的,这意味着只要持有对象的引用,它就不会被垃圾回收。只有当该对象没遇任何强引用,js引擎垃圾回收器才会销毁该对象并且回收该对象所占用的空间。

JavaScript 中对象的引用是强引用,WeakMap 和 WeakSet 可以提供部分的弱引用功能,若想在 JavaScript 中实现真正的弱引用,可以通过配合使用 WeakRef 和终结器(Finalizer)来实现。

目前在 Javascript 中,WeakMap 和 WeakSet 是弱引用对象的唯一方法:将对象作为键添加到 WeakMap 或 WeakSet 中,是不会阻止它被垃圾回收的。

WeakMap 并不是真正意义上的弱引用:实际上,只要键仍然存活,它就强引用其内容。WeakMap 仅在键被垃圾回收之后,才弱引用它的内容。

let obj = {a:1, b:2}; // 只要我们访问 obj 对象,这个对象就不会被垃圾回收

但是WeakRefs可以创建一个弱引用,对象的弱引用 是指当该对象应该被JS引擎垃圾回收时不会阻止,垃圾回收器的回收行为。

WeakRef实例具有一个方法deref,该方法返回被引用饿原始对象,如果原始对象已经被手机,啧返回undefined对象

const ref = new WeakRef({ name: 'daotin' });
let obj = ref.deref();
if (obj) {
  console.log(obj.name); // daotin
} 

使用 FinalizationRegistry 对象可以在垃圾回收器回收对象时执行回调函数。

// 构建监听对象被垃圾回收器清除的回调
const registry = new FinalizationRegistry(heldValue => {
      console.log('----', heldValue);
});

const obj = {};
const token = {};

// 注册监听
//这里:register 参数分别为:
//需要监听的对象
//执行回调函数的参数
//取消监听用的标识符
registry.register(obj, "obj deleted!", token);

// 取消监听
registry.unregister(token);

// 可能很久以后,回调执行
// ---- obj deleted!

强引用:指的是对对象的直接引用,这种引用会组织垃圾回收该对象,即使该对象的其他部分不再被访问或者使用。