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

StackOverflow https://stackoverflow.com/questions/1138565

Вопрос

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

Необходимо ли (или рекомендуется) отменить регистрацию обработчиков событий, существующих в форме и ее элементах?Если да, то как проще всего удалить всех прослушивателей из коллекции элементов?Каковы последствия невыполнения этого требования?Я использую Prototype, если это имеет значение.

Вот что я на самом деле делаю.У меня есть простая форма, например:

<form id="form">
  <input type="text" id="foo"/>
  <input type="text" id="bar"/>
</form>

Я наблюдаю различные события на входах, например:

$('foo').observe('keypress', onFooKeypress);
$('bar').observe('keypress', onBarKeypress);

и т. д.

Форма отправляется через AJAX, а ответом является новая копия формы.Я заменяю старую форму копией новой, делая что-то вроде $('form').replace(newForm).Я накапливаю кучу мусора, связанного с событиями?

Это было полезно?

Решение

Да, немного.Недостаточно, чтобы стать огромной проблемой, но в таких обстоятельствах старые версии IE будут утекать.

Начиная с Prototype 1.6.1 (в настоящее время это последний вариант выпуска), библиотека выполняет эту очистку при выгрузке страницы.Когда вы используете Prototype для добавления наблюдателя событий, он сохраняет ссылку на этот элемент в массиве;при выгрузке страницы он проходит через этот массив и удаляет всех ваших наблюдателей.

Однако, если пользователь собирается оставаться на этой странице какое-то время, использование памяти будет накапливаться в течение срока службы страницы.У вас есть несколько вариантов:

  1. Прослушивайте события на предок формы, которая никогда не заменяется.Затем в своем обработчике проверьте, откуда пришло событие.(т. е. «делегирование мероприятия»)

  2. Явно отмените регистрацию всех ваших звонков перед звонком Element#replace.В вашем примере вы бы сделали:

    $('foo', 'bar').each(Element.stopObserving);
    

Это эквивалентно вызову stopObserving без аргументов, что приводит к удалению все обработчики данного элемента.

Я бы рекомендовал вариант 1.

(Мы говорили об автоматическом удалении прослушивателя в будущей версии Prototype как часть Element#update и Element#replace, но это компромисс в производительности.)

Другие советы

События, которые не были отменены, не могут автоматически освободить свою память.Это особенно проблема в старых версиях IE.

Раньше в прототипе для этого использовалась автоматическая система сбора мусора, но в версии 1.6 этот метод был удален.Это задокументировано здесь.Означает ли удаление метода, что сборка мусора больше не осуществляется, или метод просто больше не является общедоступным, я не знаю.Также обратите внимание, что он вызывался только при выгрузке страницы, а это означает, что если ваши пользователи остаются на одной и той же странице в течение длительного времени, выполняя большое количество обновлений AJAX и DOM, утечка памяти может быть неприемлемой даже во время этого посещения одной страницы.

Всегда полезно удалить любые прослушиватели событий из элементов, удаленных из DOM, в случае сценария, упомянутого ниже Джонасом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top