慎用闭包谨防跨页面内存泄露

http://blog.thinkjs.net/archives/151

写Js的时候很多童鞋喜欢用闭包,其实闭包是非常危险的。我们先来看一个例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id= "bb" ><div id= "aa" >cc</div></div>
<script type= "text/javascript" >
function leakTest(){
     var a=[]; //用来加大闭包资源占用
     for ( var i=0;i<100000;i++){
      a.push( 'a' );
     }
     var divA=document.getElementById( 'aa' );
     divA.test= function (){};
     divA.parentNode.removeChild(divA);
}
leakTest();
</script>

在IE下这个页面每次刷新都会产生跨页面泄露,内存占用每次增大了7MB!
在这个例子中我们在leakTest()中创建了一个内部匿名函数并在dom元素aa的自定义属性test中保存了他的引用,这就产生了一个闭包。
divA.parentNode.removeChild(divA); 
这句是产生泄露的主要原因,移除了aa只不过是在dom树上将这个节点移出了,在闭包中的divA这个局部变量不会被释放,而divA中保存着aa的引用,这就形成了一个循环引用,闭包保存了dom元素aa的引用,dom元素aa的自定义属性test又保存了闭包内部的匿名函数的引用,所以在页面刷新的时候IE无法释放掉这个aa和闭包的资源,在我这个例子中就比较吓人,刷一下涨几MB内存 

那么如何解决这个问题呢?其实很简单只要我们打断divA 与aa的连接就可以了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id= "bb" ><div id= "aa" >cc</div></div>
<script type= "text/javascript" >
function leakTest(){
     var a=[]; //用来加大闭包资源占用
     for ( var i=0;i<100000;i++){
      a.push( 'a' );
     }
     var divA=document.getElementById( 'aa' );
     divA.test= function (){};
     divA.parentNode.removeChild(divA);
     divA = null // fix memory leak
}
leakTest();
</script>

建议大家不要随意使用getElementById 这些原生的方法,最好使用jQuery object去操作dom 或存储dom,这样能减少因个人疏忽引起的内存泄漏。
毕竟内存泄漏对产品来说是非常严重的问题。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值