Подтвердить что ты не робот

Нужно ли удалять прослушиватели событий перед удалением элементов?

Если у меня есть родительский элемент с дочерними элементами, у которых есть связанные с ними прослушиватели событий, мне нужно удалить эти прослушиватели событий, прежде чем я очищу родителя? (т.е. parent.innerHTML = '';). Могут ли быть утечки памяти, если прослушиватели событий не отключаются от элемента, если он удален из DOM?

4b9b3361

Ответ 1

Короткий ответ: да

Длинный ответ: большинство браузеров обрабатывают это правильно и сами удаляют эти обработчики. Есть несколько старых браузеров (IE 6 и 7, если я правильно помню), которые испортили это. Да, могут быть утечки памяти. Вам не стоит беспокоиться об этом, но вам нужно. Посмотрите этот документ.

Ответ 2

Просто обновите информацию здесь. Я тестировал различные браузеры, особенно для утечек памяти для циклически зависимых прослушивателей событий в событиях onload iframe.

Используемый код (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>

Если утечки памяти отсутствуют, используемая память будет увеличиваться примерно на 1000 кбайт или менее после запуска тестов. Однако, если есть утечка памяти, память увеличится примерно на 16 000 КБ. Удаление прослушивателя событий всегда всегда приводит к снижению использования памяти (без утечек).

Результаты:

  • IE6 - утечка памяти
  • IE7 - утечка памяти
  • IE8 - утечка памяти
  • IE9 - утечка памяти (???)
  • IE10 - утечка памяти (???)
  • IE11 - утечка памяти
  • Край (20) - отсутствие утечки памяти
  • Chrome (50) - отсутствие утечки памяти
  • Firefox (46) - трудно сказать, не просачивается плохо, а может быть, просто неэффективный сборщик мусора? Отделка с дополнительным 4 МБ без видимых причин.
  • Opera (36) - утечка памяти
  • Safari (9) - отсутствие утечки памяти

Вывод: Кровоточащие приложения могут, вероятно, уйти, не удаляя прослушиватели событий. Но я все же считаю это хорошей практикой, несмотря на раздражение.