2011-05-17 90 views
39

如果我有一個誰擁有綁定到這些事件偵聽器,做我需要刪除這些事件偵聽兒童的父元素之前,我清楚的家長嗎? (即parent.innerHTML = '';)如果事件偵聽器沒有從元素中解除綁定,那麼是否可能會發生內存泄漏?在刪除元素之前是否需要刪除事件偵聽器?

回答

24

簡短的回答:

龍答:大多數瀏覽器正確處理這一點,並刪除這些處理程序本身。有一些舊的瀏覽器(IE 6和7,如果我記得正確),這是搞砸了。是的,可能會有內存泄漏。你不必擔心這一點,但你需要。看看this document

+0

事實上:雖然目前大多數瀏覽器不會遭受它那麼多,IE 7是仍然普遍使用。另請參閱[JavaScript中的內存泄漏模式](http://www.ibm.com/developerworks/web/library/wa-memleak/)。 – 2011-05-17 16:41:51

+6

是否有人有足夠的知識來更新目前的瀏覽器市場?或者這值得單獨提問? IE7我認爲[幾乎停止](http://theie7countdown.com/),而[ie8](http://theie8countdown.com/)仍然懸而未決。 IE8處理放棄的事件偵聽器嗎? – 2014-07-10 20:41:59

+3

6年後,我想'IE <10'可以安全地認爲是過時和不使用任何人誰去在這一點上超過雅虎和AOL等網站。任何使用IE的人都可能成爲印度手機詐騙的受害者,或者得到病毒,而不是因爲事件處理程序的問題而使瀏覽器的螃蟹變慢。 – 2017-05-19 06:56:06

21

只是爲了在這裏更新的信息。我一直在測試各種瀏覽器,專門針對iframe onload事件上的循環依賴事件偵聽器的內存泄漏。

使用(的jsfiddle內存測試干擾,所以用自己的服務器來測試這個)代碼:

<div> 
    <label> 
     <input id="eventListenerCheckbox" type="checkbox" /> Clear event listener when removing iframe 
    </label> 
    <div> 
     <button id="startTestButton">Start Test</button> 
    </div> 
</div> 

<div> 
    <pre id="console"></pre> 
</div> 

<script> 

    (function() { 
     var consoleElement = document.getElementById('console'); 
     window.log = function(text) { 
      consoleElement.innerHTML = consoleElement.innerHTML + '<br>' + text; 
     }; 
    }()); 

    (function() { 
     function attachEvent(element, eventName, callback) { 
      if (element.attachEvent) 
      { 
       element.attachEvent(eventName, callback); 
      } 
      else 
      { 
       element[eventName] = callback; 
      } 
     } 

     function detachEvent(element, eventName, callback) { 
      if (element.detachEvent) 
      { 
       element.detachEvent(eventName, callback); 
      } 
      else 
      { 
       element[eventName] = null; 
      } 
     } 

     var eventListenerCheckbox = document.getElementById('eventListenerCheckbox'); 
     var startTestButton = document.getElementById('startTestButton'); 
     var iframe; 
     var generatedOnLoadEvent; 

     function createOnLoadFunction(iframe) { 
      var obj = { 
       increment: 0, 
       hugeMemory: new Array(100000).join('0') + (new Date().getTime()), 
       circularReference: iframe 
      }; 

      return function() { 
       // window.log('iframe onload called'); 
       obj.increment += 1; 
       destroy(); 
      }; 
     } 

     function create() { 
      // window.log('create called'); 
      iframe = document.createElement('iframe'); 

      generatedOnLoadEvent = createOnLoadFunction(iframe); 
      attachEvent(iframe, 'onload', generatedOnLoadEvent); 

      document.body.appendChild(iframe); 
     } 

     function destroy() { 
      // window.log('destroy called'); 
      if (eventListenerCheckbox.checked) 
      { 
       detachEvent(iframe, 'onload', generatedOnLoadEvent) 
      } 

      document.body.removeChild(iframe); 
      iframe = null; 
      generatedOnLoadEvent = null; 
     } 

     function startTest() { 
      var interval = setInterval(function() { 
       create(); 
      }, 100); 

      setTimeout(function() { 
       clearInterval(interval); 
       window.log('test complete'); 
      }, 10000); 
     } 

     attachEvent(startTestButton, 'onclick', startTest); 
    }()); 

</script> 

如果沒有內存泄漏,使用的內存會後,各地1000KB以下增加測試運行。但是,如果有內存泄漏,內存將增加約16,000kb。首先刪除事件監聽器總是會導致內存使用率降低(無泄漏)。

結果:

  • IE6 - 內存泄漏
  • IE7 - 存儲器泄漏
  • IE8 - 無存儲器泄漏
  • IE9 - 內存泄漏(???)
  • IE10 - 內存泄漏(???)
  • IE11 - 無內存泄漏
  • 邊緣(20) - 無內存泄漏
  • 鉻(50) - 沒有內存泄漏
  • 火狐(46) - 很難說,不漏得厲害,所以也許只是低效的垃圾收集器?完成一個額外的4MB沒有明顯的原因。
  • 歌劇院(36) - 沒有內存泄漏
  • 野生動物園(9) - 沒有內存泄漏

結論: 前沿的應用,也許可以與沒有刪除事件偵聽器脫身。但我仍然認爲這是一個很好的做法,儘管有這種煩惱。