javascript内存泄露
来源:广州中睿信息技术有限公司官网
发布时间:2012/10/21 23:25:16 编辑:editor 阅读 374
本文适合有一定javascript基础读者阅读。javascript内存泄露的相关问题已经是老生常谈了,但是也常常不被大家所重视,事实是一般下它对于用户体验没有多大的影响。但作为一枚苦逼奋斗的FE,

        本文适合有一定javascript基础读者阅读。

        javascript内存泄露的相关问题已经是老生常谈了,但是也常常不被大家所重视,事实是一般下它对于用户体验没有多大的影响。但作为一枚苦逼奋斗的FE,这种问题绝对要尽量避免,以此文章和大家探讨一下关于javascript的内存泄露。

        我们都知道javascript是一种垃圾收集语言,他的内存是根据对象的创建分配内存给对象的,在没有引用的情况下浏览器会把其分配的内存收回。但是由于IE对javascript对象和COM对象使用不同的垃圾收集例程(PS:FF的Mozilla's XPCOM也是),他们使用的是引用计数的模式(传说中的罪魁祸首)。

       这里必须拓展一下:javascript中最常用的垃圾收集方式是标记清除。当变量进入环境的时候,就给他贴上一个“已入狱进入环境”的标记。咳咳,事实上这个环境就像一个监狱,因为只要执行流进入了相应的环境,他们就会被使用。而变量离开的时候,他们的标记是”保释出狱离开环境“。垃圾收集器是个醒目的娃儿,他会在运行的时候给存储在内存中的所有变量加上标记。然后把环境中的变量那个以及环境中变量引用的变量(很绕口)他们的标记都去掉。然后还有标记的变量们,他们就会被删除(枪毙),因为环境中的变量已经无法访问到他们了(说!你是不是从GFW来的)。最后,垃圾收集器完成了内存清楚的工作,销毁他们的内存空间(总算是折腾完了)。  

    以上就是现在最常用的垃圾收集方式:标记清除。下面我们继续说万恶的引用计数,咳咳。其实引用计数木有什么不好,但是遇到了内存引用,他的名字就不好听了。当两个对象互相引用的时候,便构成了循环引用,其中每个对象都赋一个引用计数值1,这样的话两个引用计数就永远不会是零了,于是乎对象被判了无期徒刑,飘零在内存空间里面。

  栗子 1 :

function leak(){              var objA = new Object();              var objB = new Object();              objA.value = objB;              objB.value = objA;
}  

  如上所示,一场对象之间充满基情的循环引用产生了。

  栗子  2:

<html>
<body>
<script type="text/javscript">
function leak(){
var element = document.getElementById('elementA');
element.onclick = function(){
alert(element.id);
}
}
</script>
<div id="elementA"></div>
</body>
</html>

  上面的部分我们获取了一个ID叫做elementA的div,然后我们创建了一个元素事件处理程序的闭包。这个闭包充满基情的包含了一个element.id,咳咳。这个闭包不肯放走element包含的DOM对象。这是为什么 ?让我们深究一下吧因为匿名函数保存了一个对于leak()的函数的活动对象的引用,因此会导致无法减少element的引用数。只要匿名函数一天在,他他就会包庇着element,给他假户口让他的引用数不少于1,所以在引用计数的制度下垃圾收集策略下,因此他就会永久占有经济适用房内存空间。

       但大侦探们前端开发人员们总是无所不能的,我们做出了小小的添加,一切都不一样了——

<html>
<body>
<script type="text/javscript">
function leak(){
var element = document.getElementById('elementA');
var id = element.id;
element.onclick
= function(){
alert(id);
}
element
= null;
}
</script>
<div id="elementA"></div>
</body>
</html>

  咳咳,各位水客应该对上面的技巧毫不陌生。上述的部分,我们把element.id保存在了另外一个变量上面,接着闭包引用了变量之后消除循环引用。觉得这样就斩草除根了吗?NONONO,切记了,闭包会引用包含函数的整个活动对象,也就是说,引用了变量id,还会顺手牵出了element。即使没有直接引用,也要在最后吧element设置为null。这样就能解除对DOM对象的引用,完成内存的顺利回收。

      关于内存泄露,有很多大牛们都发表了不同的意见。如果看了我的赶脚看得不够,还有以下任意门:

http://www.codeproject.com/KB/scripting/leakpatterns.aspx   

Memory Leakage in Internet Explorer(about IE)

https://developer.mozilla.org/en/Using_XPCOM_in_JavaScript_without_leaking

Using XPCOM in JavaScript withoutleaking(about FF)



联系我们CONTACT 扫一扫
愿景:成为最专业的软件研发服务领航者
中睿信息技术有限公司 广州•深圳 Tel:020-38931912 务实 Pragmatic
广州:广州市天河区翰景路1号金星大厦18层中睿信息 Fax:020-38931912 专业 Professional
深圳:深圳市福田区车公庙有色金属大厦509~510 Tel:0755-25855012 诚信 Integrity
所有权声明:PMI, PMP, Project Management Professional, PMI-ACP, PMI-PBA和PMBOK是项目管理协会(Project Management Institute, Inc.)的注册标志。
版权所有:广州中睿信息技术有限公司 粤ICP备13082838号-2