Функции обработчика событий подчиняются той же коллекции мусора, что и другие переменные. Это означает, что они будут удалены из памяти, когда интерпретатор определит, что нет возможности получить ссылку на эту функцию. Однако простое удаление узла не гарантирует сбор мусора. Например, возьмите этот узел и связанный с ним обработчик событий
var node = document.getElementById('test');
node.onclick = function() { alert('hai') };
Теперь удалите узел из DOM
node.parentNode.removeChild(node);
Итак, node
больше не будет отображаться на вашем веб-сайте , но он явно все еще существует в памяти, как и обработчик событий
node.onclick(); //alerts hai
Пока ссылка на node
все еще доступна, это связанные свойства (из которых onclick
является одним) будет оставаться неповрежденным.
Теперь давайте попробуем его, не создавая оборванную переменную
document.getElementById('test').onclick = function() { alert('hai'); }
document.getElementById('test').parentNode.removeChild(document.getElementById('test'));
. В этом случае, похоже, нет никакого другого способа доступа к узлу DOM #test, поэтому когда цикл сбора мусора запускается, обработчик onclick
должен быть удален из памяти.
Но это очень простой случай. Использование Javascript закрытий может значительно усложнить определение собираемости мусора. Давайте попробуем привязать несколько более сложную функцию обработчика событий к onclick
document.getElementById('test').onclick = function() {
var i = 0;
setInterval(function() {
console.log(i++);
}, 1000);
this.parentNode.removeChild(this);
};
. Поэтому, когда вы нажимаете на #test, элемент будет немедленно удален, но через секунду, а затем каждую секунду, вы будет видеть увеличенный номер, напечатанный на вашей консоли. Узел удаляется, и дальнейшая ссылка на него невозможна, но, похоже, его части остаются. В этом случае сама функция обработчика событий, скорее всего, не сохраняется в памяти, а область ее создания.
Итак, ответ, который я предполагаю; это зависит. Если есть болтающиеся, доступные ссылки на удаленные узлы DOM, связанные с ними обработчики событий будут по-прежнему находиться в памяти вместе с остальными их свойствами. Даже если это не так, область, созданная функциями обработчика событий, все еще может использоваться и в памяти.
В большинстве случаев (и с радостью игнорируя IE6) лучше всего доверять сборщику мусора, чтобы выполнять свою работу, Javascript не является C в конце концов. Однако в таких случаях, как в последнем примере, важно написать некоторые деструкторные функции для неявной функции закрытия.