JS的垃圾回收机制主要是基于引用而运作的,当一个对象或一个作用域不再被引用,那么这个对象或作用域就会被垃圾回收机制回收,当然,引用的方式有很多,比如有直接的引用,原型引用,属性引用等。下面看看垃圾回收机制的两种算法
引用计数收集
最初级的垃圾收集算法,如果没有引用指向该对象,对象将被垃圾回收机制回收。看一个例子
var o = {
a:{
b:2
}
}
//这里创建了两个对象,其中外层对象被o引用,内层对象被属性a引用,因此还不能被回收
var o2 = 0//o2是第二个对这个对象的引用
o = 1;//目前只剩下o2在引用那个对象了
var oa = o2.a//目前a属性有了一个引用,因此这个对象又多了一个引用
o2 = 1;//目前只剩下oa保留有原始对象的引用
oa = 1;//原始对象已经0引用了,可以被回收
不过引用计数有一个很大的限制就是循环引用
function fn(){
let o = {};
let n = {};
o.a = n;
n.a = o;
return false
}
fn();
//这里存在着o和n之间的循环引用,因此即使函数调用完,o和n都没有被回收,就连函数作用域也没有被回收,还存在于内存中
标记清除算法
标记清除算法是根据该对象能否被获得(是否可达)来运作的。 算法假定设置一个root对象(全局对象),垃圾收集器定期从根开始,找所有从根开始引用的对象,然后继续找这些对象引用的对象,于是就能找到所有可达的对象和所有不可达的对象。
这个算法比前一个要好,因为“有零引用的对象”总是不可获得的,但是相反却不一定,参考“循环引用”。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。