JS:垃圾回收机制

94 阅读2分钟

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垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。