2011-05-17 94 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) - 没有内存泄漏

结论: 前沿的应用,也许可以与没有删除事件侦听器脱身。但我仍然认为这是一个很好的做法,尽管有这种烦恼。