如果有一个父元素,其子元素与事件侦听器绑定在一起,那么在清除父元素之前,是否需要删除这些事件侦听器?(例如,parent.innerHTML = '';)如果事件侦听器没有从从 DOM 删除的元素中解除绑定,那么是否存在内存泄漏?
parent.innerHTML = '';
简短回答: yes
长话短说: 大多数浏览器都能正确地处理这个问题,并自己删除这些处理程序。有一些老的浏览器(IE6和 IE7,如果我没记错的话)搞砸了这一切。是的,可能有内存泄漏。你不用担心这个,但你需要担心。看看 this document。
更新一下这里的信息。我一直在测试各种浏览器,特别是针对 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,000 kb。首先删除事件侦听器总是会降低内存使用(没有泄漏)。
结果:
结论: 前沿应用程序可能不会删除事件侦听器。但是我仍然认为这是一个很好的练习,尽管这很烦人。