打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
理解IE的内存泄漏问题(1):重写 - Dixin's Blog - 博客园

最近不少同学提到IE的内存泄漏问题,这个问题实际上在MSDN上的文章《Understanding and Solving Internet Explorer Leak Patterns》里已经讲过了,但我并不赞同里面的很多说法。这里我希望通过一些例子和图片来演示一下这个现象。

首先是比较直观的一类现象:pseudo leak。比如,反复重写script对象的内部文本:

<script type="text/javascript">
    
function leak()
    {
        
for(i = 0; i < 300; i++)
        {
            document.getElementById(
"script").text = (new Array(100)).join((new Array(100)).join("function bigString(){};"));
        }
        alert(
"Complete!");
    }
</script>
<script id="script">function foo(){};</script>
<href="javascript:leak();">Start leak</a>

这样会造成泄漏,但刷新或跳转可以释放内存。下图是内存使用情况:

对此,MSDN上说:“You expect that after rewriting some script that the original script won't stay around. But it really has to, because it might have been used already for event attachments and there might be outstanding reference counts. As you can see, this is a pseudo-leak. On the surface the amount of memory consumption looks really bad, but there is a completely valid reason.”感觉比较荒唐。

不仅仅是重写script对象存在问题,甚至重复创建局部变量也会有pseudo leak问题:

<script type="text/javascript">
    
function leak()
    {
        
for(i = 0; i < 300; i++)
        {
            
var bigString = (new Array(1000)).join((new Array(1000)).join("big string"));
        }
        alert(
"Complete!");
    }
</script>
<href="javascript:leak();">Start leak</a>

有一点泄漏的迹象,但不严重,刷新或跳转之后恢复了正常:

比pseudo leak更严重的是actual leak。例如,用下面的方法反复创建的局部变量是一个DOM对象:

<script type="text/javascript">
    
function divClick(){}
    
function leak()
    {
        
for(i = 0; i < 50000; i++)
        {
            
var div = document.createElement("<div onclick='divClick();'></div>");//"<div onclick=''></div>" leads to the same result
        }
        alert(
"Complete!");
    }
</script>
<href="javascript:leak();">Start leak</a>

或者反复重写一个全局变量:

var div;
function divClick(){}
function leak()
{
    
for(i = 0; i < 50000; i++)
    {
        div 
= document.createElement("<div onclick='divClick();'></div>");//"<div onclick=''></div>" leads to the same result
    }
    alert(
"Complete!");
}

甚至只是创建,完全不存在重写:

for(i = 0; i < 500000; i++)
{
    document.createElement(
"<div onclick='divClick();'></div>");// "<div onclick=''></div>" leads to the same result
}

这三种情况都将导致显著的内存泄漏,而且刷新和跳转都不能解决问题。必须关闭IE:

这就不是pseudo leak了,而是actual leak。

网上一种广为流传的说法是“JavaScript中把变量设为null,JavaScript并不会把内存释放,当下次再次定义变量时,就会覆盖此变量所在的内存。如果不设为null,JavaScript再次定义变量时,会开辟一个新的内存空间。”但这也不对。比如将上面导致严重泄漏的代码变个样子:

function leak()
{
    
for(i = 0; i < 50000; i++)
    {
        
var div = document.createElement("div");
        div.onclick 
= function(){};
    }
    alert(
"Complete!");
}

这样就不会泄漏。重复定义变量div并没有开辟新的内存空间。

这个问题属于IE的缺陷,很难摸清规律,以后如果有新的发现,将会补充在这里。

本文中代码的测试结果:

  • IE 6:存在此问题,调用CollectGarbage()不能回收;
  • IE 7:和IE 6相同;
  • Firefox 2.0.0.8:正常(不支持document.createElement("<div onclick='divClick();'></div>"),只支持document.createElement("div"));
  • Opera 9.24:和Firefox相同;
  • Safari 3.0.3:和Firefox相同。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
JavaScript:createElement
QQ空间最新免费代码大全(腾讯BUG代码,包括黄钻代
IE下script标签的readyState属性
javascript面试题,提高版 吐槽+解析
通过each方法给数组中的元素添加点击事件
JavaScript 中的内存泄露模式
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服