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

Mon code JavaSript construit une liste d'éléments LI . Lorsque je met à jour la liste, l'utilisation de la mémoire augmente et ne diminue jamais. J'ai testé dans sIEve et il montre que le navigateur conserve tous les éléments qui devaient être supprimés par les commandes $.remove() ou $.empty jQuery.

Que dois-je faire pour supprimer les nœuds DOM sans fuite de mémoire?

Voir mon autre question pour le code spécifique.

Le DOM conserve tous les nœuds DOM, même s'ils ont été retirés de l'arborescence DOM, la seule façon de supprimer ces nœuds consiste à effectuer une actualisation de la page (si vous mettez la liste dans un iframe, la rafraîchissement ne sera pas aussi perceptible)

Sinon, vous pourriez attendre que le problème soit assez mauvais pour que le collecteur d'ordures des navigateurs soit contraint (par exemple, parler de centaines de mégaoctets de noeuds inutilisés)

La meilleure pratique est de réutiliser les noeuds.

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 le ferez comme ceci:

 discardElement(this); 

Il s'agit plus d'un FYI que d'une réponse réelle, mais il est également très intéressant.

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

Les API Core Core sont conçues pour être compatibles avec un large éventail de langues, y compris les langages de script d'utilisateurs généraux et les langues les plus difficiles utilisées principalement par les programmeurs professionnels. Ainsi, les API DOM doivent fonctionner dans une variété de philosophies de gestion de la mémoire, à partir de liaisons linguistiques qui n'exposent pas la gestion de la mémoire à l'utilisateur, par l'intermédiaire de ceux (notamment Java) qui fournissent des constructeurs explicites mais fournissent automatiquement un mécanisme automatique de collecte des ordures Récupérer la mémoire inutilisée, à ceux (en particulier C / C ++) qui exigent généralement que le programmeur attribue explicitement la mémoire d'objet, vérifie où elle est utilisée et la libère explicitement pour la réutiliser. Pour assurer une API cohérente sur ces plates-formes, le DOM ne traite pas des problèmes de gestion de la mémoire, mais les quitte pour la mise en œuvre. Aucune liaison linguistique explicite définie par l'API DOM (pour ECMAScript et Java) nécessite des méthodes de gestion de la mémoire, mais les liaisons DOM pour d'autres langues (en particulier C ou C ++) peuvent nécessiter un tel support. Ces extensions seront la responsabilité de l'adaptation de l'API DOM à une langue spécifique, et non au groupe de travail DOM.

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


Comme note sur jQuery#remove et jQuery#empty : à partir de ce que je ne peux dire à aucune de ces méthodes, rien d'autre que de supprimer Object s des node DOM ou de supprimer les node DOM du document . Ils ne le suppriment que Bien sûr, cela ne signifie pas qu'il n'y a pas de mémoire allouée à ces objets (même s'ils ne sont plus dans le document ).

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

Avez-vous supprimé les auditeurs de l'événement? Cela peut provoquer des fuites de mémoire .

Le code ci-dessous ne se répercute pas sur mon IE7 et d'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 que vous pouvez essayer de repérer certaines différences avec votre code.
Je sais que IE fuit beaucoup moins lorsque vous insérez d'abord le noeud dans le DOM avant de lui faire quelque chose, par exemple: joindre des événements ou remplir sa propriété innerHTML .

Si vous devez "post-fixer" les fuites et doit le faire sans réécrire tout votre code pour prendre des fermetures, des références circulaires, etc. en compte, utilisez la méthode Douglas Crockfords Purge avant de supprimer:

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

Ou utilisez cette solution de contournement de fermeture:

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