Risposte:
JavaScript semplice
Se un elemento DOM che viene rimosso è privo di riferimenti (nessun riferimento che lo punta), allora sì : l'elemento stesso viene raccolto dal Garbage Collector e da eventuali gestori / ascoltatori di eventi associati ad esso.
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.
Però; se ci sono riferimenti che puntano ancora a detto elemento, l'elemento e i suoi listener di eventi vengono mantenuti in memoria.
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
Sarebbe giusto presumere che i metodi pertinenti in jQuery (come remove()
) funzionerebbero esattamente allo stesso modo (considerando che è remove()
stato scritto usando removeChild()
ad esempio).
Tuttavia, questo non è vero ; la libreria jQuery in realtà ha un metodo interno (che non è documentato e in teoria potrebbe essere modificato in qualsiasi momento) chiamato cleanData()
(ecco come appare questo metodo ) che pulisce automaticamente tutti i dati / eventi associati a un elemento dopo la rimozione dal DOM (essere questo via. remove()
, empty()
, html("")
ecc).
I browser più vecchi, in particolare le versioni precedenti di IE, sono noti per avere problemi di perdita di memoria a causa del fatto che i listener di eventi mantengono i riferimenti agli elementi a cui erano collegati.
Se desideri una spiegazione più approfondita delle cause, dei motivi e delle soluzioni utilizzate per correggere le perdite di memoria della versione di IE legacy, ti consiglio vivamente di leggere questo articolo MSDN su Comprensione e risoluzione dei modelli di perdite di Internet Explorer.
Alcuni altri articoli rilevanti per questo:
Rimuovere manualmente gli ascoltatori sarebbe probabilmente una buona abitudine da prendere in questo caso (solo se la memoria è così vitale per la tua applicazione e stai effettivamente prendendo di mira tali browser).
remove
metodo il più delle volte il DOM verrà cancellato completamente. (come i collegamenti turbo o qualcosa del genere). Mi chiedo come viene influenzata la memoria se lo faccio document.body.innerHTML = ''
...
per quanto riguarda jQuery:
il metodo .remove () estrae gli elementi dal DOM. Usa .remove () quando vuoi rimuovere l'elemento stesso, così come ogni cosa al suo interno. Oltre agli elementi stessi, vengono rimossi tutti gli eventi associati e i dati jQuery associati agli elementi. Per rimuovere gli elementi senza rimuovere dati ed eventi, utilizzare invece .detach ().
Riferimento: http://api.jquery.com/remove/
.remove()
codice sorgente 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;
}
apparentemente usa jQuery node.removeChild()
Secondo questo: 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.
cioè i listener di eventi potrebbero essere rimossi, ma node
esiste ancora in memoria.
removeChild
non farebbero. Entrambi ti restituiscono anche un riferimento che potresti continuare a ricollegare (in questo caso ovviamente rimane in memoria) o a lanciarlo (nel qual caso viene infine raccolto da GC e rimosso).
Non esitate a guardare heap per vedere perdite di memoria nei gestori di eventi mantenendo un riferimento all'elemento con una chiusura e l'elemento mantenendo un riferimento al gestore di eventi.
Il Garbage Collector non ama i riferimenti circolari.
Caso di perdita di memoria usuale: ammettere che un oggetto ha un riferimento a un elemento. Quell'elemento ha un riferimento al gestore. E il gestore ha un riferimento all'oggetto. L'oggetto ha riferimenti a molti altri oggetti. Questo oggetto faceva parte di una collezione che ritieni di aver gettato via senza fare riferimento alla tua collezione. => l'intero oggetto e tutto ciò a cui rimarrà rimarrà in memoria fino all'uscita dalla pagina. => devi pensare a un metodo di uccisione completo per la tua classe di oggetti o, ad esempio, fidarti di un framework mvc.
Inoltre, non esitare a utilizzare la parte della struttura di conservazione degli strumenti di sviluppo di Chrome.
Basta estendere altre risposte ...
I gestori di eventi delegati non verranno rimossi dopo la rimozione dell'elemento.
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
Ora controlla:
$._data(document.body, 'events');
Per quanto riguarda jQuery
, i seguenti metodi comuni rimuoveranno anche altri costrutti come i gestori di dati e eventi:
Oltre agli elementi stessi, vengono rimossi tutti gli eventi associati e i dati jQuery associati agli elementi.
Per evitare perdite di memoria, jQuery rimuove altri costrutti come i gestori di dati e eventi dagli elementi figlio prima di rimuovere gli elementi stessi.
Inoltre, jQuery rimuove altri costrutti come i gestori di dati e eventi dagli elementi figlio prima di sostituirli con il nuovo contenuto.
Sì, anche il Garbage Collector li rimuoverà. Potrebbe non essere sempre il caso dei browser legacy.