简介
常用的弱引用类型有
WeakMap、WeakSet、WeakRef等等,这节主要是利用弱引用来了解内存回收这一块概念,这里就拿WeakMap来举例。注意,
JavaScript中的弱引用仅适用于对象,不适用于原始值(如字符串、数字等)。此外,在使用WeakMap和WeakSet时,需要小心处理好引用计数的问题,避免出现意外的数据丢失或内存泄漏等问题。
比较
强引用
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对象属性引用了b,b对象属性又引用了a,这样他们两引用计数就永远不会归0,导致该算法无法正常工作。
- 标记-清除算法
通过遍历所有对象,以及从根出发能够访问到的对象或上下文,并将这些对象标记为“live”,其余则标记为“dead”。在标记完成后,清除所有未被标记的对象,即为可回收。
以上都还只是内存回收算法,那周期呢,因为各厂商的浏览器引擎不一样,这里我采用js红宝书这段:
通过浏览器手动回收
这里是chrome浏览器为例,F12->Performance->'垃圾箱小图标'
亲测有效,如果发现没效果,可以使用
performance.memory监听内存变化。