Отключить встроенные события javascript из элементов HTML в памяти

Как полностью отменить встроенные события javascript из своих HTML-элементов?

Я пробовал:

  • undelegating событие из элемента body
  • отключение события от элемента
  • и даже удаление атрибута события из элемента HTML

К моему удивлению, только удаление атрибута onchange (.removeAttr('onchange')) смогло предотвратить повторное срабатывание события.

<input type="text" onchange="validateString(this)"></input>

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


Итак, гипотетическая ситуация такова:

Я пишу библиотеку проверки javascript, в которой события javascript привязаны к полям ввода через встроенные атрибуты HTML:

<input type="text" onchange="validateString(this)"></input>

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

Здесь "примерный" код гипотетической валидации Library.js:

http://jsfiddle.net/CoryDanielson/jwTTf/


Чтобы протестировать, просто введите текстовое поле, а затем щелкните в другом месте, чтобы запустить событие изменения. Сделайте это при открытии и записи веб-инспектора на вкладке "Временная шкала". Выделите область временной шкалы, которая коррелирует с тем, когда вы уволили событие изменения (запустите событие изменения несколько раз), и вы увидите, что прослушиватели событий (в окне ниже) увеличиваются на 100 в каждом событии изменения. Если управление и удаление должным образом, каждый прослушиватель событий будет правильно удален до рендеринга нового ввода, но я не нашел способ правильно сделать это с помощью встроенных событий javascript.

Что делает этот код:

  • onChange, входной элемент запускает функцию проверки
  • Эта функция проверяет ввод и окрашивает границу, если успешно
  • Затем через 1 секунду (чтобы продемонстрировать утечку памяти) элемент ввода заменяется одинаковым HTML 100 раз подряд, не отменяя событие изменения (потому что я не знаю, как это сделать.., что проблема здесь). Это имитирует изменение вида в одностраничном приложении. Это создает 100 новых eventListeners в DOM, которые видны через веб-инспектора.

    • Интересное примечание. $('input').removeAttr('onchange'); фактически предотвратит запуск события onchange, но не делает мусорный сбор материала eventListener/DOM, который отображается в веб-инспекторе.

Этот снимок экрана после срабатывания события изменения 3 раза. Каждый раз 100 новых узлов DOM отображаются с одинаковым HTML, и я пытаюсь отменить событие onchange из каждого node перед заменой HTML.

enter image description here


Обновление: Я вернулся к этому вопросу и просто сделал небольшой тест с помощью JSFiddle, чтобы убедиться, что ответ действительно. Я запускал "тест" десятки раз, а затем ждал - уверен, GC прошел и позаботился о бизнесе.

enter image description here

Ответ 1

Я не думаю, что тебе есть о чем беспокоиться. Хотя памяти больше нельзя ссылаться и в конечном итоге будет собирать мусор, она все равно появляется в окне памяти Web Inspector. Память будет собираться мусором, когда GC решает собрать мусор (например, когда в браузере недостаточно памяти или после некоторого фиксированного времени). Подробная информация зависит от разработчика GC. Вы можете проверить это, просто нажав кнопку "Собрать мусор" в нижней части окна Web Insepctor. Я запускаю Chrome 23, и после ввода текста в поле проверки около 5 или 6 раз, использование памяти рушится, видимо, из-за сбора мусора.

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

Ответ 2

Мой первый sggestion должен был использовать off('change'), но, похоже, вы уже это пробовали. Возможно, причина, по которой он не работает, заключается в том, что обработчик не был привязан к .on('change'). Я не слишком много знаю о том, как jQuery обрабатывает прослушиватель, как это внутренне, но попробуйте подключиться с помощью .on('change', function ()... или .bind('change', function ()....