leo列

导航

"垃圾收集"之愚见 基本上是取自《javascript高级程序设计》的一个概括

javascript具有自动垃圾收集机制,也就是说,这个机制会找到不再使用的变量,然后释放其内存。为此,垃圾收集器(GC:Garbage collecation)会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。

垃圾收集机制具体到浏览器有两种策略:

一,标记清除。

  当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为"进入环境"。而当变量离开环境时,则将其标记为“离开环境”。"离开环境"的变量将被视为准备删除的变量,最后,垃圾收集器完成内存清除工作,销毁"离开环境"的值并回收它们所占用的内存空间。

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

 

二,引用计数

  另一种不太常用的垃圾收集策略叫做引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明一个变量并将一个引用类型的值赋给该变量时,则这个值的引用次数就是1.如果同一个值又被赋给另一个变量,则该值得引用次数加1.相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值得引用次数减1。当这个值得引用次数变成0时,则说明灭有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。

   Netscape Navigator 3.0是最早使用引用计数策略的浏览器,但很快它就遇到了一个严重的问题:循环引用循环引用指的是对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。请看下面这个例子:

function problem(){
  var objectA = new Object();
  var objectB = new Object();

  objectA.someOtherObject = objectB;
  objectB.anotherObject = objectA;
}

在这个例子中,objectA和objectB通过各自的属性相互引用;也就是说,这两个对象的引用次数都是2。当函数执行完毕后,objectA和objectB还将继续存在,因为它们的引用次数永远不会是0。为此,Netscape在Navigator4.0中放弃而来引用计数方式,转而采用标记清除来实现其垃圾收集机制。可是,引用计数导致的麻烦并未就此终结。原因是:IE中有一部分对象并不是原生javascript对象。例如,其BOM和DOM中的对象就是使用C++以COM(Component Object Model,组件对象模型)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。因此,即使IE的javascript引擎是用用标记清除策略来实现的,但javascript访问的COM对象依然是基于引用计数策略的。换句话说,只要在IE中涉及COM对象,就会存在循环引用的问题。

posted on 2012-09-19 18:12  leo列  阅读(179)  评论(0编辑  收藏  举报