Jeśli element DOM zostanie usunięty, to czy jego słuchacze również zostaną usunięte z pamięci?

Jeśli element DOM zostanie usunięty, czy jego słuchacze również zostaną usunięci z pamięci?

Author: dsgriffin, 2012-09-21

6 answers

Nowoczesne przeglądarki

Plain JavaScript

Jeśli element DOM, który jest usuwany, jest wolny od referencji (brak referencji na niego wskazujących), to yes-sam element jest wychwytywany przez garbage collector, jak również przez programy obsługi zdarzeń/słuchacze z nim związane.

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.

Jednakże; jeśli istnieją odniesienia, które nadal wskazują na wspomniany element, element i jego słuchacze zdarzeń są zachowane w pamięć.

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

Można by założyć, że odpowiednie metody w jQuery (takie jak remove()) będą działać dokładnie w ten sam sposób (biorąc pod uwagę, że {[2] } zostało napisane przy użyciu removeChild() na przykład).

Jednak to nie jest prawda; biblioteka jQuery faktycznie ma wewnętrzną metodę (która jest nieudokumentowana i teoretycznie może być zmieniona w dowolnym momencie) o nazwie cleanData() (oto jak wygląda ta metoda ), która automatycznie czyści wszystkie dane / zdarzenia związane z elementem po usunięciu z DOM (być to via. remove(), empty(), html("") itp.).


Starsze przeglądarki

Starsze przeglądarki-w szczególności starsze wersje IE - są znane z problemów z wyciekiem pamięci ze względu na to, że słuchacze zdarzeń przechowują odniesienia do elementów, do których zostały dołączone.

Jeśli chcesz bardziej dogłębne wyjaśnienie przyczyn, wzorców i rozwiązań używanych do naprawy wycieków pamięci starszych wersji IE, w pełni polecam Czytaj ten artykuł MSDN na zrozumienie i rozwiązywanie wzorców wycieku Internet Explorer.

Jeszcze kilka artykułów na ten temat:

Ręczne usuwanie słuchaczy samemu byłoby prawdopodobnie dobrym nawykiem, aby wejść w tym przypadku (tylko jeśli pamięć jest tak istotna dla Twojej aplikacji i faktycznie jesteś targetowanie takich przeglądarek).

 329
Author: dsgriffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-10 17:44:31

Odnośnie jQuery:

The .metoda remove () usuwa elementy z DOM. Użyj .Usuń (), gdy chcesz usunąć sam element, jak również jak wszystko w środku. Oprócz samych elementów, wszystkie powiązane zdarzenia i dane jQuery powiązane z elementami są usuwane. Aby usunąć elementy bez usuwania danych i zdarzeń, użyj .detach() zamiast tego.

Numer referencyjny: http://api.jquery.com/remove/

JQuery v1.8. 2 .remove() kod źródłowy:

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;
}

Najwyraźniej jQuery używa node.removeChild()

Zgodnie z tym: 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.

Ie event listeners może zostać usunięty, ale node nadal istnieje w pamięci.

 24
Author: Sreenath S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-21 11:04:38

Nie wahaj się obserwować sterty, aby zobaczyć wycieki pamięci w procedurach obsługi zdarzeń, które przechowują odniesienie do elementu z zamknięciem, a element przechowuje odniesienie do procedury obsługi zdarzeń.

Garbage collector nie lubi odniesień okrągłych.

Zwykły przypadek wycieku pamięci: przyznaj, że obiekt ma ref do elementu. Ten element ma ref do obsługi. A opiekun ma ref do obiektu. Obiekt posiada refy do wielu innych obiektów. Ten obiekt był częścią kolekcji, którą myślisz, że wyrzucili je z twojej kolekcji. => cały obiekt i wszystko, do czego się odnosi pozostanie w pamięci do momentu zakończenia strony. = > musisz pomyśleć o kompletnej metodzie zabijania dla swojej klasy obiektu lub zaufać na przykład frameworkowi mvc.

Ponadto, nie wahaj się użyć części drzewa zatrzymującego w Chrome Dev tools.

 8
Author: lib3d,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-07 00:03:27

Jeśli chodzi o jQuery, następujące wspólne metody usuwają również inne konstrukcje, takie jak procedury obsługi danych i zdarzeń:

Usunąć()

Oprócz samych elementów, wszystkie powiązane zdarzenia i dane jQuery powiązane z elementami są usuwane.

Pusty()

Aby uniknąć wycieków pamięci, jQuery usuwa inne konstrukcje, takie jak procedury obsługi danych i zdarzeń z elementów potomnych przed usunięciem elementów siebie.

Html()

Dodatkowo, jQuery usuwa inne konstrukcje, takie jak procedury obsługi danych i zdarzeń z elementów potomnych przed zastąpieniem tych elementów nową zawartością.

 7
Author: Jaskey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 06:39:21

Tylko rozszerzam inne odpowiedzi...

Delegowane procedury obsługi zdarzeń nie będą usuwane po usunięciu elementu.

$('body').on('click', '#someEl', function (event){
  console.log(event);
});

$('#someEL').remove(); // removing the element from DOM

Teraz sprawdź:

$._data(document.body, 'events');
 7
Author: Lucky Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-08 11:58:26

Tak, śmieciarka też je usunie. Może jednak nie zawsze tak być w przypadku starszych przeglądarek.

 1
Author: Darin Dimitrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-21 09:43:10