利用js的Weak弱引用类型,带你彻底了解内存回收机制

228 阅读2分钟

简介

常用的弱引用类型有WeakMapWeakSetWeakRef等等,这节主要是利用弱引用来了解内存回收这一块概念,这里就拿WeakMap来举例。

注意,JavaScript中的弱引用仅适用于对象,不适用于原始值(如字符串数字等)。此外,在使用WeakMapWeakSet时,需要小心处理好引用计数的问题,避免出现意外的数据丢失或内存泄漏等问题。

比较

强引用

let obj = { name: "foo" };
let arr = [obj];obj = null;
​
// 等一段时间打印,5秒内手动内存回收
setTimeout(() => {
    console.log(arr[0]); // 输出:{ name: "foo" }
}, 5000);

弱引用

let obj = { name: "foo" };
const weakRef = new WeakRef(obj);obj = null;
​
// 等一段时间打印,5秒内手动内存回收
setTimeout(() => {
    // 如果 obj 被回收了,则 weakRef.deref() 返回 undefined
    console.log(weakRef.deref()); // 输出:undefined
}, 5000);

注意:可能因浏览器和 JavaScript 引擎的不同,可能会对最终打印结果有所影响,建议两个例子分开文件运行。

内存回收

window.gc

虽然目前有小部分浏览器提供了 window.gc() 方法来手动触发内存回收,但这个方法并不是通用的。

等待浏览器内存回收周期

在 JavaScript 中,内存回收算法主要使用了引用计数与标记-清除两种方式

  • 引用计数算法

通过记录每个对象被其它对象所引用的次数,当引用次数为零时即视为可回收。但是由于循环引用的存在,也就是a对象属性引用了bb对象属性又引用了a,这样他们两引用计数就永远不会归0,导致该算法无法正常工作。

  • 标记-清除算法

通过遍历所有对象,以及从根出发能够访问到的对象或上下文,并将这些对象标记为“live”,其余则标记为“dead”。在标记完成后,清除所有未被标记的对象,即为可回收

以上都还只是内存回收算法,那周期呢,因为各厂商的浏览器引擎不一样,这里我采用js红宝书这段:

333111.png

通过浏览器手动回收

这里是chrome浏览器为例,F12->Performance->'垃圾箱小图标'

fdfsd12.png

亲测有效,如果发现没效果,可以使用performance.memory监听内存变化。