垃圾回收机制——总结自《JavaScript高级程序设计》

垃圾收集(garbage collection)

在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收彻底实现了自动管理。这种垃圾收集机制的原理其实很简单:找出那些再也不继续使用的变量,而后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预约的收集时间),周期性地执行这一操做。算法

垃圾收集器必须跟踪哪一个变量有用哪一个变量没用,对于再也不有用的变量打上标记,以备未来收回其占用的内存。用于标识无用变量的策略可能会因实现而异,但具体到浏览器中的实现,则一般有两个策略:标记清除和引用计数浏览器

标记清除(mark-and-sweep)

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

到 2008 年为止, IE、 Firefox、 Opera、 Chrome 和 Safari 的 JavaScript 实现使用的都是标记清除式的垃圾收集策略(或相似的策略),只不过垃圾收集的时间间隔互有不一样。code

引用计数(reference counting)

当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。若是同一个值又被赋给另外一个变量,则该值的引用次数加 1。相反,若是包含对这个值引用的变量又取得了另一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,于是就能够将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。对象

但在采用引用计数策略的实现中,当函数执行完毕后,函数内部循环引用的对象还将继续存在,由于它们的引用次数永远不会是 0。假如这个函数被重复屡次调用,就会致使大量内存得不到回收。正是因为这个缘由,Netscape在Navigator 4.0中放弃了引用计数方式,转而采用垃圾回收。ip

//循环引用实例
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}

IE 中有一部分对象并非原生 JavaScript 对象。例如,其 BOM 和 DOM 中的对象就是使用 C++以 COM(Component Object Model,组件对象模型)对象的形式实现的,而 COM 对象的垃圾收集机制采用的就是引用计数策略。所以,即便 IE 的 JavaScript 引擎是使用标记清除策略来实现的,但JavaScript 访问的 COM 对象依然是基于引用计数策略的。换句话说,只要在 IE 中涉及 COM 对象,就会存在循环引用的问题。为了不相似这样的循环引用问题,最好是在不使用它们的时候手工断开原生 JavaScript 对象与DOM 元素之间的链接(赋值为null)。
IE9 把 BOM 和 DOM 对象都转换成了真正的 JavaScript 对象。这样,就避免了两种垃圾收集算法并存致使的问题,也消除了常见的内存泄漏现象。内存

总结:内存的自动回收基于两种策略:其中的引用计数策略在对象循环引用时不可用,IE8及如下的DOM和BOM对象操做深受其害;目前,IE9+和其余四大浏览器基本支持标记清除方式,区别仅在于垃圾回收的周期不一样。开发

相关文章
相关标签/搜索