Antworten:
Einfaches JavaScript
Wenn ein entferntes DOM-Element referenzfrei ist (keine Verweise darauf), dann ja - das Element selbst wird vom Garbage Collector sowie allen damit verbundenen Event-Handlern / Listenern aufgenommen.
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.
Jedoch; Wenn es noch Referenzen gibt, die auf dieses Element verweisen, bleiben das Element und seine Ereignis-Listener im Speicher.
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
Es wäre fair anzunehmen, dass die relevanten Methoden in jQuery (wie z. B. remove()
) genauso funktionieren würden (wenn remove()
man bedenkt , removeChild()
dass sie beispielsweise mit geschrieben wurden).
Dies ist jedoch nicht wahr ; Die jQuery-Bibliothek verfügt tatsächlich über eine interne Methode (die nicht dokumentiert ist und theoretisch jederzeit geändert werden kann) mit dem Namen cleanData()
(so sieht diese Methode aus ), die beim Entfernen aus dem DOM automatisch alle Daten / Ereignisse bereinigt, die einem Element zugeordnet sind (sei dies über. remove()
, empty()
, html("")
usw.).
Ältere Browser - insbesondere ältere Versionen von IE - haben bekanntermaßen Probleme mit Speicherverlusten, da Ereignis-Listener Verweise auf die Elemente behalten, an die sie angehängt wurden.
Wenn Sie eine ausführlichere Erläuterung der Ursachen, Muster und Lösungen zur Behebung älterer Speicherlecks in der IE-Version wünschen, empfehlen wir Ihnen, diesen MSDN-Artikel zum Verständnis und Lösen von Internet Explorer-Leckmustern zu lesen .
Einige weitere relevante Artikel:
Das manuelle Entfernen der Listener selbst wäre in diesem Fall wahrscheinlich eine gute Angewohnheit (nur wenn der Speicher für Ihre Anwendung so wichtig ist und Sie tatsächlich auf solche Browser abzielen).
remove
Methode. Meistens wird das DOM nur vollständig gelöscht. (wie Turbolinks oder so). Ich frage mich, wie das Gedächtnis beeinflusst wird, wenn ich document.body.innerHTML = ''
...
zu jQuery:
Die Methode .remove () entfernt Elemente aus dem DOM. Verwenden Sie .remove (), wenn Sie das Element selbst sowie alles darin entfernen möchten. Zusätzlich zu den Elementen selbst werden alle gebundenen Ereignisse und jQuery-Daten, die den Elementen zugeordnet sind, entfernt. Verwenden Sie stattdessen .detach (), um die Elemente zu entfernen, ohne Daten und Ereignisse zu entfernen.
Referenz: http://api.jquery.com/remove/
jQuery v1.8.2 .remove()
Quellcode:
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;
}
anscheinend verwendet jQuery node.removeChild()
Demnach: 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.
Das heißt, Ereignis-Listener werden möglicherweise entfernt, sind jedoch node
noch im Speicher vorhanden.
removeChild
Handlern nicht möglich wäre. Beide geben Ihnen auch eine Referenz zurück, die Sie behalten können, um letztere wieder anzubringen (in diesem Fall bleibt sie offensichtlich im Speicher) oder wegzuwerfen (in diesem Fall wird sie schließlich von GC aufgenommen und entfernt).
Zögern Sie nicht, Heap zu beobachten, um Speicherlecks in Ereignishandlern zu sehen, die einen Verweis auf das Element mit einem Abschluss und das Element, das einen Verweis auf den Ereignishandler enthält.
Garbage Collector mag keine Zirkelverweise.
Üblicher Speicherverlustfall: Geben Sie zu, dass ein Objekt einen Verweis auf ein Element hat. Dieses Element hat einen Verweis auf den Handler. Und der Handler hat einen Verweis auf das Objekt. Das Objekt hat Verweise auf viele andere Objekte. Dieses Objekt war Teil einer Sammlung, von der Sie glauben, dass Sie sie weggeworfen haben, indem Sie sie aus Ihrer Sammlung entfernt haben. => Das gesamte Objekt und alles, worauf es verweist, bleibt bis zum Verlassen der Seite im Speicher. => Sie müssen über eine vollständige Kill-Methode für Ihre Objektklasse nachdenken oder beispielsweise einem MVC-Framework vertrauen.
Zögern Sie nicht, den Retention Tree-Teil der Chrome-Entwicklungstools zu verwenden.
Nur andere Antworten erweitern ...
Handler für delegierte Ereignisse werden beim Entfernen von Elementen nicht entfernt.
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
Überprüfe jetzt:
$._data(document.body, 'events');
Bezüglich jQuery
die folgenden gängigen Methoden werden auch andere Konstrukte wie Daten- und Ereignishandler entfernt:
Zusätzlich zu den Elementen selbst werden alle gebundenen Ereignisse und jQuery-Daten, die den Elementen zugeordnet sind, entfernt.
Um Speicherverluste zu vermeiden, entfernt jQuery andere Konstrukte wie Daten- und Ereignishandler aus den untergeordneten Elementen, bevor die Elemente selbst entfernt werden.
Darüber hinaus entfernt jQuery andere Konstrukte wie Daten- und Ereignishandler aus untergeordneten Elementen, bevor diese Elemente durch den neuen Inhalt ersetzt werden.
Ja, der Garbage Collector entfernt sie ebenfalls. Dies kann jedoch bei älteren Browsern nicht immer der Fall sein.