2010-09-24 12 views
45

Mi código JavaSript crea una lista de elementos LI. Cuando actualizo la lista, el uso de memoria crece y nunca baja. Probé en sIEve y muestra que el navegador mantiene todos los elementos que se suponía que debían eliminarse mediante los comandos $.remove() o $.empty jQuery.Cómo eliminar elementos DOM sin pérdidas de memoria?

¿Qué debo hacer para eliminar los nodos DOM sin la pérdida de memoria?

Consulte my other question para ver el código específico.

Respuesta

8

¿Has eliminado a los oyentes del evento? Eso can cause memory leaks.

+0

incluso hacer por cada elemento $ (this) .unbind() html ("") remove(); – podeig

+2

Pensé que jQuery elimina los controladores de eventos automáticamente, cuando haces element.remove(), ¿no? – jayarjo

+0

@jayarjo - lo hace – vsync

43

El DOM conserva todos los nodos DOM, incluso si se han eliminado del árbol DOM en sí, la única forma de eliminar estos nodos es hacer una actualización de página (si coloca la lista en un iframe, la actualización no ser tan notable)

de lo contrario, se podría esperar a que el problema de conseguir bastante malo que el colector navegadores de basura se ve obligado a la acción (hablando de cientos de megabytes de nodos no utilizados aquí)

mejor práctica consiste en reutilizar los nodos.

EDIT: Prueba esto:

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

para usarlo en su contexto, lo haría así:

discardElement(this); 
+9

No sabía acerca de "El DOM conserva todos los nodos DOM, incluso si se han eliminado del árbol DOM sí mismo" ¿Quiere decir que la función $ .remove() no ¿no hacer nada? – podeig

+0

Cuantos MegaBite deben usarse para ejecutar el recolector de basura. Creo que 150Mb debe ser suficiente. Pero no funciona para mí. – podeig

+0

Editado, prueba el código provisto. –

2

El código de abajo no se escape en mi IE7 y otra navegadores:

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

Puede ser que usted puede tratar de detectar alguna diferencia s con tu código
Sé que IE pierde mucho menos cuando inserta primero el nodo en el DOM antes de hacer algo, por ejemplo: adjuntarle eventos o completar su propiedad innerHTML.

13

Esto es más de FYI que una respuesta real, pero también es bastante interesante.

Desde el W3C DOM especificación núcleo (http://www.w3.org/TR/DOM-Level-2-Core/core.html):

Los Core DOM APIs están diseñados para ser compatible con una amplia gama de idiomas, incluidos los lenguajes de scripting de usuario general y los lenguajes más desafiantes utilizados principalmente por programadores profesionales. Por lo tanto, las DOM API necesitan operar en una variedad de filosofías de administración de memoria, desde enlaces de lenguaje que no exponen la administración de memoria al usuario, pasando por aquellos (especialmente Java) que proporcionan constructores explícitos pero proporcionan un mecanismo automático de recolección de basura para automáticamente reclamar memoria no utilizada, a aquellos (especialmente C/C++) que generalmente requieren que el programador asigne explícitamente memoria de objeto, rastrear dónde se usa y liberarla explícitamente para su reutilización. Para garantizar una API consistente en todas estas plataformas, el DOM no aborda en absoluto los problemas de administración de memoria, sino que los deja para la implementación. Ninguno de los enlaces de lenguaje explícitos definidos por la DOM API (para ECMAScript y Java) requieren ningún método de gestión de memoria, pero los enlaces DOM para otros lenguajes (especialmente C o C++) pueden requerir tal soporte. Estas extensiones serán responsabilidad de quienes adaptan la DOM API a un idioma específico, no al Grupo de trabajo DOM.

En otras palabras: la gestión de la memoria se deja a la implementación de la especificación DOM en varios idiomas. Tendría que buscar en la documentación de la implementación DOM en javascript para encontrar cualquier método para eliminar un objeto DOM de la memoria, que no es un hack. (Sin embargo, existe muy poca información sobre el sitio del MDC en ese tema.)


Como una nota en jQuery#remove y jQuery#empty: de lo que puedo decir que ninguno de estos métodos hace otra cosa que no sea la eliminación de Object s de DOM node s o eliminar DOM node s del document. Solo eliminan Eso, por supuesto, no significa que no haya memoria asignada a estos objetos (a pesar de que ya no están en el document).

Editar: El pasaje anterior era superfluo ya que obviamente jQuery no puede hacer maravillas y trabajar con la implementación DOM del navegador usado.

+1

de jQuery .remove() API: "... Además de los elementos en sí, se eliminan todos los eventos enlazados y los datos de jQuery asociados con los elementos. Para eliminar los elementos sin eliminar datos y eventos, use .detach() en su lugar." – vsync

+0

Usted dijo que" por lo que puedo decir, ninguno de estos métodos hace otra cosa que eliminar Objetos de los nodos DOM o eliminar los nodos DOM del documento "... así que cité de la API que hace más que eso. todos los eventos vinculados. – vsync

+1

El contexto era la asignación de memoria. Pero, bueno, allí sorprendí el pasaje de 'jQuery'. – FK82

Cuestiones relacionadas