垃圾回收机制

垃圾回收机制—GC

Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。

原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行

1.那什么样的垃圾会被回收呢?

不再使用的变量也就是生命周期结束的变量,当然只可能是局部变量,全局变量的生命周期直至浏览器卸载页面才会结束。局部变量只在函数的执行过程中存在,而在这个过程中会为局部变量在栈或堆上分配相应的空间,以存储它们的值,然后在函数中使用这些变量,直至函数结束,而闭包中由于内部函数的原因,外部函数并不能算是结束。

2.什么时候进行垃圾回收?

会按照固定的时间间隔周期性的执行。

3.怎样回收这些垃圾?

(1)引用计数

跟踪记录每个值被引用的次数。当声明一个变量并将引用类型的值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次 数加1.相反,如果包含对这个值引用的变量又取得另外一个值,则这个值的引用次数减1.当这个值的引用次数变成0时,则说明没有办法访问这个值了,因此就 可以将其占用的内存空间回收回来。

var  a={};      //对象{}的引用计数为1

b=a;             //对象{}的引用计数为1+1

a=null;          //对象{}的引用计数为2-1

所以这时对象{}不会被回收;

IE 6, 7 对DOM对象进行引用计数回收, 这样简单的垃圾回收机制,非常容易出现循环引用问题导致内存不能被回收, 进行导致内存泄露等问题。

demo1:

var btn=$("button");

btn.onclick=function(){   

//当这里也可以访问到btn,说明function内部存在btn的引用

};

demo2:

function a(){ 

varx={};

vary={};

x.a=y;

y.a=x;

}

a();

函数a执行完后,本来x,y对象都应该在垃圾回收阶段被回收, 可是由于存在循环引用,也不能被回收。

解决方法:

手工解除循环引用,将变量设置为null意味着切断变量与它此前引用的值之间的连接。

(2)标记清除

js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。

function test(){

var a = 10 ;//被标记 ,进入环境

var b = 20 ;//被标记 ,进入环境

}

test();  //执行完毕 之后 a、b又被标离开环境,被回收。

垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。

推荐阅读更多精彩内容