博客迁移至 freefe.cc
分类: JavaScript
2013-03-14 23:07:35
对于其他语言来说,如C,C++,需要开发者手动的来跟踪内存,而JS的垃圾回收机制使得JS开发人员无需再关系内存的情况,所有的内存分配以及回收都会由垃圾回收器自动完成,执行环境会对执行过程中占有的内存负责。其原理就是找出那些不在被使用的变量,然后释放其所占有的内存。回收器一般是按照固定的时间间隔或者预设的时间进行处理的。
e.g. 1
function test1(){
var i ={name:’nyf’};
}
function test2(){
var i ={name:’nyf’};
return i;
}
var m1 = test1();
var m2 = test2();
一般来说在e.g.1中,当 test1调用时,进入 test1 的环境,那么内存中会开辟存放 {name:’nyf’} 对象的内存,当调用结束后,出了 test1 的环境,那么该内存会被JS引擎中的垃圾回收器自动释放其内存。
在test2中,对象被返回,并且被变量 m2 所指向,所以虽然说在调用完 test2 后出了其环境,但是由于m2仍然持续着对对象的链接关系,所以该对象不会被释放。
但是我们需要注意上述两个例子函数中其实均有2块的内存占用,一个是变量名 i 以及对象 {name:’nyf’} ,i中只是保存着对该对象的地址值。运行test2 未被释放的只是对象,变量名i在2个方法中均被释放,i值才是JS引擎真正需要处理的目标。对于返回的对象,已经返回到上一层的环境,当没有变量再对其进行引用的时候自然也会变会被释放(个人理解)
目前JS的垃圾回收机制无非就是两种:1.标记清除(make-and-sweep) 2.引用计数(reference counting)
1.标记清除:标记清除简单的来说就是给各个变量名打上 YES or NO的标签以供JS引擎进行处理(当然打什么标签自己理解即可)。在和执行上下文类似的的环境中当变量名称进入环境的时候,那么变量会被打上 YES。一般来说是绝对不会释放被打上 YES 标签的变量内存的,一旦变量在出了该环境时,变会被打上 NO 标签(和作用域貌似有点像),JS引擎会在一定时间间隔或者设置的时间来进行扫描,对NO标签的进行剔除以释放其内存。
2.引用计数(查了很多资料,还是无法找到其真正的计算方式)
一般来说,引用计数的含义是跟踪记录每个值被引用的次数。当声明一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数便是1,如果同一个值又被赋给另一个变量,则该值的引用次数加1,相反,如果包含对这个值引用的变量又取得了另一个值,则这个值的引用次数减1。当这个值的引用次数为0时,说明没有办法访问到它了,因而可以将其占用的内存空间回收。(感觉是有问题的)
对于引用计数,我们需要知道如果具有循环引用,那么其计数问题就会暴露,导致计数永远不为0而无法释放内存,导致内存泄露,具体事例如下:
e.g.2
function(){
var a = {};
var b = {};
b.pro = a;
a.pro=b;
}
如果e.g.2使用引用计数的话就会导致问题,内存无法被释放,导致内存无故消耗占用。
除了一些极老版本的IE,目前市面上的JS引擎基本采用标记清除来除了垃圾回收。但是需要注意的是IE中的DOM由于机制问题,是采用了引用计数的方式,所以会有循环引用的问题,如:
e.g.3
var ele = document.getElementById(“element”);
var obj = new Object();
ele.obj = obj;
obj.ele = ele;
这边就会倒是问题,内存无法再执行完毕后释放
解决方法其实也很简单,当所有的代码完毕末尾处只需要对变量进行 null 赋值即可。
有很多不足与错误,希望各位指出~谢谢~
引用计数详解:http://blog.csdn.net/armman/article/details/1714911