您的位置:首页 > Web前端 > JavaScript

JavaScript垃圾回收机制解析

2014-03-25 13:18 344 查看

JavaScript垃圾回收机制解析

JavaScript具有自动垃圾收集机制,也就是说,执行环境(一般为浏览器)会负责管理代码执行过程中使用的内存.这种垃圾回收机制的原理很简单:找出那些不再使用的变量,然后释放他们所占用的内存.为此垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性的执行这一操作.

浏览器实现这一机制通常有以下两种策略:

标记清除(maker-and sweep)

这是javascript中最常用的垃圾收集方式.当变量进入环境时(例如,在函数中声明一个变量)时,就将这个变量声明为"进入环境".从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入到相应的环境,就有可能用到它们,而当变量离开环境时,就将变量标记为"离开环境".

垃圾收集器会为存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式).当变量"离开环境"时,垃圾收集器就会为变量加上"销毁"标记.最后,垃圾收集器完成内存清理工作.销毁那些带有"销毁"标记的变量并回收它们所占用的内存空间.

IE,Chrome,Firefox, Opera和Safari都是使用这种策略(或类似的方式)来实现垃圾清除的,只不垃圾回收的时间间隔不同.

引用计数(reference counting)

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

虽然这种方式很简单,也很容易理解,但它存在一个非常的问题:循环引用.循环引用是指对象A包含对对象B的引用,而对象B又包含对对象A的引用.如下:

Function problem()

{

Var objectA=new Object();

Var objectB=new Object();

objectA.property=objectB;

objectB.property=objectA;

}

在标记清除的策略中,由于上而的函数执行完毕后,这两个对象都离开了作用域,因此这种相互引用不存在问题.但在引用计数的实现中,当函数执行完毕,objectA和objectB还将继续存在,因为它用的引用计数永远不会为0.假如这种重复引用的函数被调用多次,则会导致大量的内存无法回收.

基本上没有浏览器用这种回收机制,但是这种麻烦并没有得到终止.

我们知道,IE中有一部分对象并不是原生的javascript对象,例如,BOM和DOM中的对象就是使用C++以COM(Component object model 组件对象模型)对象的形式来实现的.而COM的垃圾回收机制采用的就是引用计数的策略.因此,即使IE的javascript引擎是用标记清除策略来实现的,但javascript访问的COM对象依然是基于引用计数策略.换句话说,只要在IE中涉及DOM对象,就会存在循环引用的问题.下面简单的例子,展示了使用DOM对象产生的循环引用问题:

Var element=document.getElementById("some_element");

Var myObject=new Object();

Myobject.element=element;

Element.object=myObject;

为了避免循环引用问题的发生,最好在不再使用它们的时候,手动最两个对象之间的互相引用断开.如下

myObject.element=null;

Element.object=null;

将变量的值设为null,就意味着切断变量与它此前引用的值之间的连接.当垃圾收集器下次运行时,就会删除这些值并回收它们所占用的内存.

摘处<<javascript高级程序设计(第二版)>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: