锁定老帖子 主题:IE下闭包引起跨页面内存泄露探讨
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-08-14
liudaoru 写道 那么这种情况该如何解释那?这种情况也没有太大的内存泄漏
<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'); } this.divA=document.getElementById('aa'); this.divA.kk=function(){}; document.getElementById("bb").removeChild(this.divA); } new leakTest(); </script> 你确定上面代码,IE下会产生内存泄露? |
|
返回顶楼 | |
发表时间:2008-08-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.kk=function(){}; divA.parentNode.removeChild(divA); } leakTest(); </script> 这是liudaoru的代码,但没有产生内存泄露(不信你可以试试) <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'); } this.divA=document.getElementById('aa'); this.divA.kk=function(){}; document.getElementById("bb").removeChild(this.divA); } new leakTest(); //产生个匿名对象 </script> 为什么呢?如此相似的代码,一个产生了泄露一个却没有。 个人观点: 楼主用一个var定义了个局部变量divA,闭包<=>div就有了循环引用。 liudaoru用this。this.divA没有被闭包占用(可能是this的特殊性)。于是就有了,匿名对象->divA->闭包,闭包却没有引用diva,也就没有循环引用。 |
|
返回顶楼 | |
发表时间:2008-08-22
achun 写道 有深度呀,第一次看到这样的文章,长知识了。
顺手测试了一下www.jquery.com似乎同样有泄露, 不过我不知道,leaks栏中有红色的和绿色的差别是什么呀? 看来写js还要考虑leak问题呀! 做程序真.....的很...苦...... 有泄露就.....要修...补...... 啊......... 根据我的经验,红色表示你上次查看(show leaks)后新出现的leaks。 |
|
返回顶楼 | |
发表时间:2009-02-05
这好像是IE的内存管理问题,好像在哪里看到,如果js与js对象互引用不会出现这种情况,如果js与native object互引用特别是用到闭包那这种内存泄露存在的可能性是极高的。
比较可笑的是有人一直去怪IE的内存管理而不去找到让其内存泄露的原因并改之! |
|
返回顶楼 | |
发表时间:2009-02-05
引用计数的gc方式是不大可能处理js对象和dom对象相互引用的,最好的处理方法是时刻保持清醒即时断开这种互引用就行了。
|
|
返回顶楼 | |
发表时间:2009-02-06
最后修改:2009-02-07
trarck 写道 请注意:
这是楼主的代码,也是会产生内存泄露的代码: <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.kk=function(){}; divA.parentNode.removeChild(divA); } leakTest(); </script> 这是liudaoru的代码,但没有产生内存泄露(不信你可以试试) <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'); } this.divA=document.getElementById('aa'); this.divA.kk=function(){}; document.getElementById("bb").removeChild(this.divA); } new leakTest(); //产生个匿名对象 </script> 为什么呢?如此相似的代码,一个产生了泄露一个却没有。 个人观点: 楼主用一个var定义了个局部变量divA,闭包<=>div就有了循环引用。 liudaoru用this。this.divA没有被闭包占用(可能是this的特殊性)。于是就有了,匿名对象->divA->闭包,闭包却没有引用diva,也就没有循环引用。 估计是因为闭包只引用函数变量(印象中,闭包是面向函数的编程时引入的概念),而this.divA实际上是leakTest的成员变量(实例变量),是外部可以访问的变量。 所以闭包并没有对this.divA的引用。 如果把上面的第二个代码改成: <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'); } this.divA=document.getElementById('aa'); var self = this.divA; this.divA.kk=function(){}; document.getElementById("bb").removeChild(this.divA); } new leakTest(); //产生个匿名对象 </script> 这样闭包中有了对self的引用,因此就行成了this.divA对DOM节点( document.getElementById('aa') )的引用,而DOM节点又有对this.divA的引用,这就行成了循环引用(circular reference),资源无法回收。 |
|
返回顶楼 | |