弱引用与垃圾回收:WeakMap
中的key是弱引用
那么问题来了:什么是弱引用
简单来说是:对象、数组、函数
但是标准概念是:弱引用(Weak Reference)是一种对象引用方式,它允许对象被垃圾回收器(Garbage Collector, GC)回收,即使还有对这个对象的弱引用存在。
这里提到的允许对象被垃圾回收器(Garbage Collector, GC)回收,这就是Vue3使用WeakMap
而不是Map
的原因之一了。我们来举个例子:
const wMap = new WeakMap();
const map = new Map();
(function () {
const foo = { foo: 1 };
const bar = { bar: 2 };
wMap.set(foo, 1);
map.set(bar, 2);
})();
console.log(wMap) //WeakMap { <items unknown> }
console.log(map)//Map(1) { { bar: 2 } => 2 }
由这段代码可以看出:
-
WeakMap
可以减少内存泄漏风险 -
WeakMap
允许对象在没有其他引用时被自动回收,这有助于自动释放不再需要的对象,从而减少内存占用 -
Vue 3使用
WeakMap
来缓存代理对象,防止对象被重复代理,这样可以避免不必要的内存占用和性能损耗
根据第三点,我们就可以来看看Vue3源码中对WeakMap
的使用了。
这里举一小段例子(reactive.ts)
import { isObject } from "@vue/shared";
const reactiveMap = new WeakMap();
const enum ReactiveFlags {
IS_REACTIVE = "_v_isReactive", //标记是否之前已经new Proxy过
}
export function reactive(target) {
if (isObject(target)) {
return;
}
if (target[ReactiveFlags.IS_REACTIVE]) {
return target;
}
//如果之前有缓存过,就不需要反复进行proxy代理
if (reactiveMap.get(target)) {
return reactiveMap.get(target);
}
const proxy = new Proxy(target, {
get(target, key, receiver) {
if (key === ReactiveFlags.IS_REACTIVE) return true;
// 依赖收集
track(target, "get", key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
},
});
//缓存代理对象
reactiveMap.set(target, proxy);
return proxy;
}
补充:
什么是值类型(与弱引用相对应)
简单来说是:字符串、数字
但是标准概念是:值类型(Value Types)是指在计算机编程中,变量直接存储其值的数据类型。