JavaScirpt垃圾回收机制
垃圾回收.jpg
JavaScript具有自动垃圾回收机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。
在C和C++中,开发人员的一项很重要的任务就是手工跟踪内存的使用情况,这是造成许多问题的根源。而在JS中,内存的分配实现了自动的管理。
这种垃圾回收机制的原理其实很简单:找出不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔,周期性地执行这一操作。
- 垃圾收集的方式
一、标记清除
这是JS最常用的垃圾收集方式。当变量进入环境(eg:在函数中声明一个变量)时,就将它标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。
而标记的方式有很多种。比如:像计算机组成原理中通过翻转某个特殊的位,来记录一个变量何时进入环境;或者使用一个“进入/离开环境的”变量列表来跟踪哪个变量发生了变化。
垃圾收集器在运行的时候,会给存储在内存的所有变量都加上标记,然后随着程序的执行,慢慢去掉环境中的变量以及被环境中变量引用的变量的标记。而在此之后,存有标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。
最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收它们所占用的内存空间。
目前,IE、Firefox、Chrome、Safari和Opera等主流的浏览器都使用了标记清除式的垃圾收集策略(或类似的策略),只不过,垃圾收集的周期略有不同。
坚持住,能看到这行文字,说明你不再是小白了。
二、引用计数
这是一种不太常见的垃圾收集策略。简单地说是跟踪并记录每个值被引用的次数。
Netscape Navigator 3.0是最早使用引用计数策略的浏览器,但很快它就遇到了一个严重的问题:循环引用。(对象A中包含一个指针对象B的指针,而对象B中也包含一个指向对象A的引用。)
function problem(){
var objA = new Object();
var objB = new Ojbect();
objA.someOtherObject = objB;
objB.anotherObject = objA;
}
在
IE9之前的BOM和DOM都不是真正的JS对象,因此存在大量的内存泄露现象。导致循环引用的情况不止这些,其他情况后面再介绍。为了避免类似这样的循环引用问题,最好是在不使用它们的时候,将变量设置为
null,切断变量与它此前引用的值的关系。
三、性能问题
说到垃圾收集器多长时间运行一次,不禁让人联想到IE因此声明狼藉的性能问题。IE的垃圾收集器是根据内存分配量运行的。
具体一点说:就是256个变量,4096个对象字面量和数组元素或者64KB的字符串。达到上述任何一个值,垃圾收集器就会运行。很显然,这种机制的问题在于,如果一个脚本中包含足够多的变量,该脚本很可能会在其生命周期中一直保有那么多的变量。而这样一来,垃圾收集器就不得不频繁地运行。结果,由此引发的严重性能问题促使IE7重写了垃圾收集机制。
事实上,在有的浏览器中可以手动触发垃圾收集的过程。但通常不建议这么做。
在IE中,调用window.CollectGarbage();在Opera7以上的版本,调用window.opera.collect()方法会立即执行垃圾收集。
四、管理内存
开发人员一般不必操心内存管理的问题,但由于操作系统分配给Web浏览器的可用内存数量通常比桌面应用程序的少——这样做的目的主要是出于安全的考虑,目的是防止运行网页时耗尽系统内存而导致系统崩溃。
为了确保占用最少的内存,让页面获得更好的性能。力求让程序在运行时,只保存必要的数据。一旦数据一再有用,最好设置为null来释放其引用——这个做法叫解除引用。
function createPerson(name){
var localPerson = name;
localPerson.name = name;
return localPerson;
}
var globalPerson = createPerson("learninginto");
//手动接触globalPerson的引用
globalPerson = null;
注意:解除一个值的引用,并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
五、小结
- 离开作用域的值,将被自动标记为可以回收,因此将在垃圾收集期间被删除。
- “标记清除”是目前主流的垃圾收集算法。
- “引用清除”的思想是跟踪并记录所有值被引用的次数。JS引擎目前都不再使用这种算法。
- 当代码中存在循环引用现象时,“引用计数”算法会导致问题。
- 解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用。









网友评论