Respostas:
JavaScript simples
Se um elemento DOM removido é livre de referência (sem referências apontando para ele), então sim - o próprio elemento é capturado pelo coletor de lixo, bem como pelos manipuladores / ouvintes de eventos associados a ele.
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.
Contudo; se houver referências que ainda apontem para o referido elemento, o elemento e seus ouvintes de eventos serão retidos na memória.
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
Seria justo supor que os métodos relevantes no jQuery (como remove()
) funcionariam exatamente da mesma maneira (considerando que remove()
foi escrito usando, removeChild()
por exemplo).
No entanto, isso não é verdade ; a biblioteca jQuery realmente possui um método interno (que não é documentado e, em teoria, pode ser alterado a qualquer momento) chamado cleanData()
(eis como esse método se parece ) que limpa automaticamente todos os dados / eventos associados a um elemento após a remoção do DOM (seja esta via. remove()
, empty()
, html("")
etc.).
Navegadores mais antigos - especificamente versões mais antigas do IE - são conhecidos por terem problemas de vazamento de memória devido ao fato de os ouvintes de eventos manterem as referências aos elementos aos quais foram anexados.
Se você quiser uma explicação mais aprofundada das causas, padrões e soluções usadas para corrigir vazamentos de memória da versão IE herdada, recomendo totalmente que você leia este artigo do MSDN sobre Compreendendo e resolvendo padrões de vazamento do Internet Explorer.
Mais alguns artigos relevantes para isso:
Remover você mesmo os ouvintes manualmente provavelmente seria um bom hábito para entrar nesse caso (apenas se a memória for vital para o seu aplicativo e você estiver realmente direcionando esses navegadores).
remove
método. na maioria das vezes, o DOM será apagado completamente. (como links turbo ou algo assim). Eu estou querendo saber como a memória é afetada se eu fizer document.body.innerHTML = ''
...
em relação ao jQuery:
o método .remove () remove elementos do DOM. Use .remove () quando quiser remover o próprio elemento, bem como tudo o que estiver dentro dele. Além dos próprios elementos, todos os eventos vinculados e dados do jQuery associados aos elementos são removidos. Para remover os elementos sem remover dados e eventos, use .detach ().
Referência: http://api.jquery.com/remove/
Código .remove()
fonte do 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;
}
aparentemente o jQuery usa node.removeChild()
De acordo com isso: 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.
ou seja, os ouvintes de eventos podem ser removidos, mas node
ainda existem na memória.
removeChild
. Os dois também retornam uma referência que você pode manter para recolocar o último (nesse caso, obviamente, permanece na memória) ou jogar de maneira (nesse caso, é eventualmente captado pelo GC e removido).
Não hesite em observar o heap para ver vazamentos de memória nos manipuladores de eventos, mantendo uma referência ao elemento com um fechamento e o elemento mantendo uma referência ao manipulador de eventos.
Coletor de lixo não gosta de referências circulares.
Caso usual de vazamento de memória: admita que um objeto tenha uma ref para um elemento. Esse elemento tem uma referência ao manipulador. E o manipulador tem uma referência ao objeto. O objeto tem referências a muitos outros objetos. Esse objeto fazia parte de uma coleção que você acha que jogou fora, sem referência a ele da sua coleção. => todo o objeto e tudo o que ele se refere permanecerão na memória até a saída da página. => você precisa pensar em um método completo de eliminação para sua classe de objeto ou confiar em uma estrutura mvc, por exemplo.
Além disso, não hesite em usar a parte da árvore de retenção das ferramentas de desenvolvimento do Chrome.
Apenas estendendo outras respostas ...
Os manipuladores de eventos delegados não serão removidos após a remoção do elemento.
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
Agora verifica:
$._data(document.body, 'events');
Em relação a jQuery
, os seguintes métodos comuns também removerão outras construções, como manipuladores de dados e eventos:
Além dos próprios elementos, todos os eventos vinculados e dados do jQuery associados aos elementos são removidos.
Para evitar vazamentos de memória, o jQuery remove outras construções, como manipuladores de dados e eventos dos elementos filhos, antes de remover os próprios elementos.
Além disso, o jQuery remove outras construções, como manipuladores de dados e eventos dos elementos filhos, antes de substituir esses elementos pelo novo conteúdo.
Sim, o coletor de lixo também os removerá. Nem sempre pode ser o caso de navegadores herdados.