51 votes

Comment supprimer des éléments DOM sans fuite de mémoire?

Mon Javascript crée une liste d'éléments "LI". Lorsque je mets à jour la liste, l'utilisation de la mémoire augmente et ne diminue jamais. Je me demande ce que je devrais faire pour supprimer les nœuds DOM sans fuite de mémoire.

J'ai testé dans sIEve et il montre que le navigateur conserve tous les éléments que je pensais avoir été supprimés par les commandes $ .remove () ou $ .empty jQuery.

Aidez-moi!!!

46voto

Andrew Dunn Points 7465

Le DOM conserve tous les nœuds DOM, même si elles ont été supprimées de l'arbre du DOM lui-même, la seule façon de supprimer ces nœuds est de faire un rafraichissement de la page (si vous mettez de la liste dans une iframe de l'actualisation ne sera pas aussi perceptible)

Sinon, vous pouvez attendre que le problème d'obtenir assez mauvais que les navigateurs garbage collector est forcé dans l'action (en parlant des centaines de mégaoctets de nœuds inutilisés ici)

La meilleure pratique est de réutiliser les nœuds.

EDIT: Essayez ceci:

var garbageBin;
window.onload = function ()
    {
    if (typeof(garbageBin) === 'undefined')
        {
        //Here we are creating a 'garbage bin' object to temporarily 
        //store elements that are to be discarded
        garbageBin = document.createElement('div');
        garbageBin.style.display = 'none'; //Make sure it is not displayed
        document.body.appendChild(garbageBin);
        }
    function discardElement(element)
        {
        //The way this works is due to the phenomenon whereby child nodes
        //of an object with it's innerHTML emptied are removed from memory

        //Move the element to the garbage bin element
        garbageBin.appendChild(element);
        //Empty the garbage bin
        garbageBin.innerHTML = "";
        }
    }

Pour l'utiliser dans votre contexte, vous serait-il faire comme ceci:

discardElement(this);

17voto

FK82 Points 1464

C'est plus un FYI que d'une réelle réponse, mais il est également tout à fait intéressant.

À partir du W3C DOM de base spécification (http://www.w3.org/TR/DOM-Level-2-Core/core.html):

Le Core DOM Api sont conçus pour être compatibles avec un large éventail de langues, y compris à la fois générales de l'utilisateur, les langages de script et le plus difficile langues utilisé par la plupart des programmeurs professionnels. Ainsi, les DOM Api besoin pour fonctionner dans une variété de gestion de la mémoire de philosophies, de liaisons de langage qui n'exposez pas la gestion de la mémoire de l'utilisateur, par l'intermédiaire de ceux (notamment Java) qui explicite les constructeurs, mais de fournir automatiquement un mécanisme de collecte des déchets pour récupérer automatiquement la mémoire inutilisée, à ceux (surtout en C/C++) qui exigent généralement le programmeur explicitement allouer de la mémoire d'objet, de la piste où il est utilisé, et explicitement, gratuit pour les réutiliser. Pour assurer une API cohérente dans l'ensemble de ces plates-formes, les DOM ne traite pas des problèmes de gestion mémoire, mais à la place des feuilles de ces pour la mise en œuvre. Ni l'un ni l'explicite liaisons de langage défini par l'API DOM (ECMAScript et Java) exiger de la gestion de la mémoire de méthodes, mais DOM liaisons pour les autres langues (surtout en C ou C++) peut exiger d'un tel soutien. Ces extensions seront de la responsabilité de ceux adaptation de l'API DOM pour une langue spécifique, pas les DOM Groupe de Travail.

En d'autres termes: gestion de la mémoire est laissé à la mise en œuvre de la spécification DOM dans différentes langues. Vous devez regarder dans la documentation de la DOM implémentation en javascript afin de trouver une méthode pour supprimer un objet DOM à partir de la mémoire, qui n'est pas un hack. (Il y a cependant très peu d'informations sur le MDC site sur ce sujet).


Comme une note sur jQuery#remove et jQuery#empty: à partir de ce que je peux dire, aucune de ces méthodes n'est rien d'autre que de supprimer Objects depuis les DOM nodes ou en supprimant des DOM nodes à partir de l' document. Ils ne supprimer Que, bien sûr, ne signifie pas qu'il n'y a pas de mémoire allouée à ces objets (même si elles ne sont pas dans l' document plus).

Edit: Le passage ci-dessus est superflu puisque de toute évidence jQuery ne peut pas faire des merveilles et de travailler autour de la DOM de la mise en œuvre du navigateur utilisé.

9voto

Skilldrick Points 33002

Avez-vous supprimé des écouteurs d'événement? Cela peut provoquer des fuites de mémoire .

2voto

Mic Points 13418

Le code ci-dessous ne coule pas sur mon IE7 et les autres navigateurs:

 <html>
<head></head>
<body>
    <a href="javascript:" onclick="addRemove(this)">add</a>
    <ul></ul>
    <script>
        function addRemove(a) {
            var ul = document.getElementsByTagName('UL')[0],
                li, i = 20000;
            if (a.innerHTML === 'add') {
                while (i--) {
                    li = document.createElement('LI');
                    ul.appendChild(li);
                    li.innerHTML = i;
                    li.onclick = function() {
                        alert(this.innerHTML);
                    };
                }
                a.innerHTML = 'remove';
            } else {
                while (ul.firstChild) {
                    ul.removeChild(ul.firstChild);
                }
                a.innerHTML = 'add';
            }
        }
    </script>
    </body>
</html>
 

Peut-être pouvez-vous essayer de repérer certaines différences avec votre code.
Je sais que IE fuit beaucoup moins lorsque vous insérez d'abord le nœud dans le DOM avant d'y faire quoi que ce soit, par exemple: y attacher des événements ou remplir sa propriété innerHTML .

0voto

Jens Points 124

Si vous avez de "post-fix" de fuite, et il doit le faire sans avoir à réécrire tout le code pour prendre des fermetures, des circulaires, des références, etc en compte, l'utilisation de Douglas Crockfords de Purge méthode avant de supprimer:

http://javascript.crockford.com/memory/leak.html

Ou utiliser cette fermeture-fix solution de contournement:

http://laurens.vd.oever.nl/weblog/items2005/closures/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X