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

来源:互联网 发布:小米手环2无睡眠数据 编辑:程序博客网 时间:2024/06/10 22:30

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(){
    vara=[];//用来加大闭包资源占用
    for(vari=0;i<100000;i++){
     a.push('a');
    }
    vardivA=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(){
    vara=[];//用来加大闭包资源占用
    for(vari=0;i<100000;i++){
     a.push('a');
    }
    vardivA=document.getElementById('aa');
    divA.test=function(){};
    divA.parentNode.removeChild(divA);
    divA =null// fix memory leak
}
leakTest();
</script>

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



原创粉丝点击