Ответы:
Простой JavaScript
Если удаляемый элемент DOM не содержит ссылок (ссылки на него отсутствуют), то да - сам элемент выбирается сборщиком мусора, а также любыми обработчиками / прослушивателями событий, связанными с ним.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
b = null;
// A reference to 'b' no longer exists
// Therefore the element and any event listeners attached to it are removed.
Тем не мение; если есть ссылки, которые все еще указывают на указанный элемент, элемент и его прослушиватели событий сохраняются в памяти.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
// A reference to 'b' still exists
// Therefore the element and any associated event listeners are still retained.
JQuery
Было бы справедливо предположить, что соответствующие методы в jQuery (например, remove()
) будут функционировать точно так же (учитывая, что они remove()
написаны, removeChild()
например, с использованием).
Однако это не так ; библиотека jQuery на самом деле имеет внутренний метод (который недокументирован и теоретически может быть изменен в любое время), который называется cleanData()
(вот как выглядит этот метод ), который автоматически удаляет все данные / события, связанные с элементом, после удаления из DOM (будь это через. remove()
, empty()
и html("")
т. д.).
Известно, что в старых браузерах, в частности в старых версиях IE, возникают утечки памяти из-за того, что слушатели событий держат ссылки на элементы, к которым они были присоединены.
Если вам требуется более подробное объяснение причин, шаблонов и решений, используемых для устранения утечек памяти в старых версиях IE, я настоятельно рекомендую вам прочитать эту статью MSDN, посвященную пониманию и устранению шаблонов утечек в Internet Explorer.
Еще несколько статей, относящихся к этому:
Ручное удаление слушателей, вероятно, будет хорошей привычкой в этом случае (только если память так важна для вашего приложения, и вы на самом деле ориентируетесь на такие браузеры).
remove
метода. Большую часть времени DOM будет просто полностью стёрт. (как турбо ссылки или что-то). Мне интересно, как влияет память, если я делаю document.body.innerHTML = ''
...
относительно jQuery:
метод .remove () извлекает элементы из DOM. Используйте .remove (), когда вы хотите удалить сам элемент, а также все внутри него. В дополнение к самим элементам удаляются все связанные события и данные jQuery, связанные с элементами. Чтобы удалить элементы без удаления данных и событий, используйте вместо этого .detach ().
Ссылка: http://api.jquery.com/remove/
.remove()
Исходный код jQuery v1.8.2 :
remove: function( selector, keepData ) {
var elem,
i = 0;
for ( ; (elem = this[i]) != null; i++ ) {
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
}
return this;
}
по-видимому, JQuery использует node.removeChild()
В соответствии с этим: https://developer.mozilla.org/en-US/docs/DOM/Node.removeChild ,
The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.
т.е. слушатели событий могут быть удалены, но node
все еще существуют в памяти.
removeChild
не делают . Оба также возвращают вам ссылку, которую вы можете сохранить, чтобы присоединить последнюю (в этом случае она, очевидно, остается в памяти) или выбрасывать (в этом случае GC в конечном итоге берется и удаляется).
Не стесняйтесь смотреть кучу, чтобы увидеть утечки памяти в обработчиках событий, сохраняющих ссылку на элемент с закрытием, и элемент, хранящий ссылку на обработчик события.
Сборщик мусора не любит циклические ссылки.
Обычный случай утечки памяти: допустим, что объект имеет ссылку на элемент. Этот элемент имеет ссылку на обработчик. И обработчик имеет ссылку на объект. Объект имеет ссылки на множество других объектов. Этот объект был частью коллекции, которую, как вы думаете, вы выбросили, не ссылаясь на нее из своей коллекции. => весь объект и все, на что он ссылается, останется в памяти до выхода из страницы. => вам нужно подумать о полном методе уничтожения для вашего класса объектов или, например, довериться фреймворку mvc.
Кроме того, не стесняйтесь использовать часть «Сохранение дерева» инструментов Chrome dev.
Просто расширяю другие ответы ...
Обработчики делегированных событий не будут удалены при удалении элемента.
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
Теперь проверьте:
$._data(document.body, 'events');
Что касается jQuery
следующих общих методов, также будут удалены другие конструкции, такие как обработчики данных и событий:
В дополнение к самим элементам удаляются все связанные события и данные jQuery, связанные с элементами.
Чтобы избежать утечек памяти, jQuery удаляет другие конструкции, такие как данные и обработчики событий, из дочерних элементов перед удалением самих элементов.
Кроме того, jQuery удаляет другие конструкции, такие как данные и обработчики событий, из дочерних элементов перед заменой этих элементов новым содержимым.
Да, сборщик мусора также удалит их. Впрочем, это может случиться не всегда с устаревшими браузерами.