初步了解ES6的时候,翻到偏后一些的章节总会有一种莫名的不安,很多概念比较抽象,业务中也很难体现出用途,但又不得不去了解,不然总觉得自己算不上熟悉ES6吧。没错,今天我就以weakMap和weakSet为引导,来说说浏览器的垃圾回收机制。
weakSet
WeakSet
是一种集合,其中的元素只能是对象和Symbol
,并且这些对象是弱引用的。什么是弱引用,我们观察一下这个简单的代码片段:
let xm1 = { name: '路桥川' };
let xm2 = { name: '钟白' };
xm1 = null; // 此时xm1不再引用任何对
// xm1引用的对象将被标记为可回收
// 引出标记和清除的概念
标记-清除 (Mark-and-Sweep)
标记-清除是最常用的GC策略。工作流程如下:
- 标记:GC遍历所有变量,标记活动(正在使用的)变量。
- 清除:GC再次遍历,清除未标记的变量,回收其内存。
let obj = {name:'毕十三'}
let ws = new WeakSet()//只能存储symbol和对象,存储其他类型会报错
ws.add(obj)
console.log(ws);//输出:WeakSet { <items unknown> }
// 虽然obj并不为空,但其实在整个上下文中并没有有效引用,weakSet中的这个obj已经被回收
引用计数 (Reference Counting)
引用计数是另一种策略,通过追踪每个值被引用的次数来工作:
- 当值的引用次数为0时,表示该值不再被使用,可以被回收。
循环引用问题
引用计数策略可能会遇到循环引用问题,导致内存无法释放。
function problem() {
const objectA = {};
const objectB = {};
objectA.ref = objectB;
objectB.ref = objectA;
}
problem();
在上面的例子中,objectA
和objectB
互相引用,形成循环。在只使用引用计数的GC中,这会导致内存泄漏。