2010-01-04 137 views

回答

28

绝大多数泄漏我们当您在JavaScript对象和DOM节点等主机对象之间进行参考循环时,特别在IE6-7中讨论JavaScript。

在IE6中这是特别有害的,因为当你离开页面时你没有得到回忆;它已经消失,直到你退出浏览器。在IE7中清除页面现在可以返回内存,但是当你有一个长时间运行的应用程序时,你仍然会遇到困难。 IE8通过将DOM节点转换为本地JavaScript对象而不是主机对象来正确地解决了这个问题。 (你仍然可以在IE8中通过在参考循环中包含其他非本机对象,如ActiveX对象来触发泄漏)。

在所有浏览器中随机出现的潜在的小内存泄漏仍然存在,特别是旧版本。但是没有一种方法可以轻松分类并避免出现类似于IE refloop问题的情况。

+1

+1:长期寻找这个perl的智慧。 – 2010-09-08 12:24:12

+0

@Marco Demaio嗯,这个http://ecmascript.stchur.com/blogcode/ie_innerhtml_memleak/leak.html仍然在IE9中以标准或怪癖模式泄漏(win7 64bit),请务必在监视专用字节时使用进程资源管理器..叹了口气.. – 2012-08-02 01:41:38

+0

@AlexanderN:实际上IE8 WXP你建议的页面不会泄漏。我使用简单的“Windows任务管理器”(“性能”选项卡)来查看页面是否泄漏,在这种情况下,您会看到“PF Usage”增加得越来越多。 – 2012-08-17 15:49:09

17

添加到bobince答案,我做了一些测试IE8

我试图在http://www.javascriptkit.com/javatutors/closuresleak/index.shtml

他们正在泄漏内存中没有一个提供几乎所有的例子了(至少在可感知的方式),除例子去除仍附有他们事件的子节点。

这种类型的例子我认为最好在他的queuetest2中用Douglas Crockford来解释。

这一个在IE8仍然出现内存泄漏,它是很容易测试,只需运行the test script,看着Windows任务管理器 - 性能 - PF使用率。你会看到PF Usage每循环增加近1MB(非常快)。

在IE8

内存被释放在页面卸载(如导航到一个新的页面重新加载在同一页),显然也当完全关闭浏览器。因此,为了使最终用户能够感知IE8上的内存泄露(因为降低了系统性能),他需要长时间保持在同一页面上,这在目前的日子里可能会频繁发生在AJAX上,但是这个页面还需要做数百个子节点去除元素并附带事件

道格拉斯Crockford的测试强调添加了10000节点浏览器,然后取出,这是极好的展示你的问题,但在现实生活中我从未有过一个网页,删除超过10个元素。INMHO通常使用display: none而不是删除整个节点集合,这就是为什么我不使用removeChild那么多。


对于谁可能更感兴趣的是IE8内存泄漏上面解释的,我做了另一个测试,它似乎MEM泄漏不到位的appendChild/removeChild添加使用innerHTML时都在IE8显示/删除附加事件的子元素。因此很明显,道格拉斯Crockford的purge function(由他提出,以防止内存泄漏在IE)是没有必要再在使用IE8时innerHTML至少...

EDITED得益于以下 4esn0k评论) ...而且道格拉斯Crockford purge function在IE8上完全不起作用,他的代码var a = d.attributes返回在IE8上运行时添加的属性(或任何其他onevent属性)(它们在IE7上返回)。

道格拉斯Crockford的说:

“清除功能应该删除任何元件之前被调用,要么 由removeChild之方法,或通过 设置的innerHTML属性”。

我这里提供测试代码:

<body>  
    <p>queuetest2 similar to the one provided by Douglas Crockford 
    at http://www.crockford.com/javascript/memory/leak.html 
    <br>but this one adds/removes spans using innerHTML 
    instead of appendChild/removeChild.</p> 

    <div id="test"></div>  
    <script> 
     /* ORIGINAL queuetest2 CODE FROM DOUGLAS CROCKFORD IS HERE 
      http://www.crockford.com/javascript/memory/queuetest2.html */ 

     (function (limit, delay) 
     { 
      var n = 0; 
      var add = true; 

      function makeSpan(n) 
      { 
       var div = document.getElementById('test'); 
       //adding also an inline event to stress more the browser 
       div.innerHTML = "<span onmouseover=\"this.style.color = '#00ff00';\">" + n + "</span>"; 
       var s = div.getElementsByTagName('span')[0]; 
       s.onclick = function(e) 
       { 
        s.style.backgroundColor = 'red'; 
        alert(n); 
       }; 
       return s; 
      } 

      function process(n) 
      { 
       if(add)      
       s = makeSpan(n); 
       else 
       s.parentNode.innerHTML = ""; //removing span by clearing the div innerHTML 
       add = !add; 
      } 

      function loop() 
      { 
       if (n < limit) 
       { 
        process(n); 
        n += 1; 
        setTimeout(loop, delay); 
       } 
      } 

      loop(); 
     })(10000, 10); 

    </script> 
</body> 
+0

“道格拉斯克罗克福德净化功能”对IE 8来说有帮助吗?似乎,由于IE8(在IE8模式下,不兼容模式)“s.onclick”未映射到“onclick”属性,因此清除无法在属性中找到“onclick”。我对吗? – 4esn0k 2012-01-26 06:40:05

+0

@ 4esn0k:对不起,但我不确定你的意思。 – 2012-01-31 17:16:08

+1

var s = document.createElement('div'); s.onclick = function(){}; var a = s.attributes; for(var i = 0; i 4esn0k 2012-02-01 06:27:21