JS中的强引用和弱引用

121 阅读2分钟

什么是强引用和弱引用

本文用到 FinalizationRegistryWeakRef ,不熟悉的同学可以自行去 mdn 查看

let obj = {
  a: 1,
  b: 2
}

let obj2 = obj;

const registry = new FinalizationRegistry((heldValue) => {
  console.log(heldValue + '变量被回收了');
});

registry.register(obj, 'obj');

obj = null

console.log(obj2)

在这个案例中我想达到的效果为 当 obj = null ,就将 { a:1, b:2 } 这个空间销魂, 但是 obj2指向这个内存空间,GC检测到有“钥匙”指向这个内存空间, 所以内存是销毁不了的, 因为他们是强引用的。

image.png

那当我们修改一下案例

let obj = {
  a: 1,
  b: 2
}

let obj2 = new WeakRef(obj);

const registry = new FinalizationRegistry((heldValue) => {
  console.log(heldValue + '变量被回收了');
});

registry.register(obj, 'obj');

obj = null

console.log('obj的a:', obj2.deref()?.a)

setTimeout(() => console.log('obj的a: 10s后', obj2.deref()?.a), 10000)

image.png

我们用 weakRefobj 包裹起来赋值给 obj2, 此时 obj2 连接着 { a:1, b:2 } 这个内存空间,但是他们之间的连接是弱引用的,所以obj = null可以内存空间回收了,当回收后,可以看到已经打印为undefined 的了,

这就是强引用和弱引用的区别

weakMap 和 weakSet

weakMapweakSet 就是弱引用的一种实现

WeakMapkey 只能是 Object 类型

WeakSet 只能是对象的集合,而不能像 Set 那样,可以是任何类型的任意值。

为什么要求他们必须为对象呢? 因为弱引用只是针对复杂数据类型的

验证weakMap

let obj = {
  a: 1,
  b: 2
}
const registry = new FinalizationRegistry((heldValue) => {
  console.log(heldValue + '变量被回收了');
});

registry.register(obj, 'obj');

const map = new Map();
map.set(obj, { x: 100, y: 200 });

console.log('map.get(obj)', map.get(obj))
obj = null

image.png

可以看到 用普通的 map 并不会触发 obj 的回收

当我们换成 weakMap

const weakmap = new WeakMap();
weakmap.set(obj, { x: 100, y: 200 });

console.log('weakmap.get(obj)', weakmap.get(obj))
obj = null

image.png

可以看到 weakMapobj 的引用不会影响到 obj 的回收