2010-01-04 54 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