什么是强引用和弱引用
本文用到 FinalizationRegistry 和 WeakRef ,不熟悉的同学可以自行去 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检测到有“钥匙”指向这个内存空间, 所以内存是销毁不了的, 因为他们是强引用的。
那当我们修改一下案例
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)
我们用 weakRef 将 obj 包裹起来赋值给 obj2, 此时 obj2 连接着 { a:1, b:2 } 这个内存空间,但是他们之间的连接是弱引用的,所以obj = null可以内存空间回收了,当回收后,可以看到已经打印为undefined 的了,
这就是强引用和弱引用的区别
weakMap 和 weakSet
weakMap 和 weakSet 就是弱引用的一种实现
WeakMap 的 key 只能是 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
可以看到 用普通的 map 并不会触发 obj 的回收
当我们换成 weakMap
const weakmap = new WeakMap();
weakmap.set(obj, { x: 100, y: 200 });
console.log('weakmap.get(obj)', weakmap.get(obj))
obj = null
可以看到 weakMap 对 obj 的引用不会影响到 obj 的回收