簡體   English   中英

在刪除元素之前是否需要刪除事件偵聽器?

[英]Do I need to remove event listeners before removing elements?

如果我有一個父元素,其子元素綁定了事件偵聽器,我是否需要在清除父元素之前刪除這些事件偵聽器? (即, parent.innerHTML = ''; )如果事件偵聽器未從元素中解除綁定(如果它從 DOM 中刪除),是否會發生內存泄漏?

只是為了更新這里的信息。 我一直在測試各種瀏覽器,特別是針對 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 - 沒有內存泄漏
  • Edge (20) - 無內存泄漏
  • Chrome (50) - 沒有內存泄漏
  • Firefox (46) - 很難說,不會泄漏很嚴重,所以也許只是低效的垃圾收集器? 無緣無故以額外的 4MB 結束。
  • Opera (36) - 無內存泄漏
  • Safari (9) - 無內存泄漏

結論:出血邊緣應用程序可能可以通過不刪除事件偵聽器而逃脫。 但我仍然認為這是一個很好的做法,盡管有煩惱。

簡短回答:是的

長答案:大多數瀏覽器都會正確處理這個問題並自己刪除這些處理程序。 有一些較舊的瀏覽器(IE 6 和 7,如果我沒記錯的話)將其搞砸了。 是的,可能存在內存泄漏。 您不必擔心這一點,但您需要這樣做。 看看這個文件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM