2012-04-10 10 views
10

Una de las ventajas de jQuery.data frente a las propiedades de expansión sin procesar (atributos arbitrarios que puede asignar a los nodos DOM) es que jQuery.data es "seguro de referencias circulares y por lo tanto libre de pérdidas de memoria". Un artículo de Google titulado "Optimizing JavaScript code" entra en más detalles:Explicación precisa de JavaScript <-> DOM cuestión de referencia circular

Las pérdidas de memoria más comunes para aplicaciones web implican circulares referencias entre el motor de scripts de JavaScript y C++ objetos de los navegadores implementación del DOM (por ejemplo, entre el código JavaScript script motor y la infraestructura COM de Internet Explorer, o entre el motor de JavaScript y la infraestructura Firefox XPCOM).

enumera dos ejemplos de patrones de referencia circulares:

  • elemento DOM → controlador de eventos alcance → cierre → DOM

  • elemento DOM → través expando → intermediario objeto → elemento DOM

Sin embargo, si un ciclo de referencia entre un nodo DOM y un objeto JavaScript produce una pérdida de memoria, ¿no significa esto que cualquier controlador de eventos no triviales (p. onclick) producirá tal fuga? No veo cómo es incluso posible que un controlador de eventos para evitar un ciclo de referencia, debido a la forma en que lo veo:

  • El elemento DOM referencia al controlador de eventos.

  • El controlador de eventos hace referencia al DOM (directa o indirectamente). En cualquier caso, es casi imposible evitar hacer referencia a window en cualquier controlador de eventos interesante, salvo escribir un setInterval bucle que lee acciones de una cola global.

Puede alguien dar una explicación precisa del DOM problema de referencia circular JavaScript ↔? Cosas que me gustaría aclarar:

  • ¿Qué navegadores se efectúan? Un comentario en la fuente de jQuery menciona específicamente IE6-7, pero el artículo de Google sugiere que Firefox también se ve afectado.

  • ¿Las propiedades de expansión y los controladores de eventos son de alguna manera diferentes con respecto a las pérdidas de memoria? ¿O ambos fragmentos de código son susceptibles al mismo tipo de pérdida de memoria?

    // Create an expando that references to its own element. 
    var elem = document.getElementById('foo'); 
    elem.myself = elem; 
    
    // Create an event handler that references its own element. 
    var elem = document.getElementById('foo'); 
    elem.onclick = function() { 
        elem.style.display = 'none'; 
    }; 
    
  • Si una memoria de páginas fugas debido a una referencia circular, no la fuga persistir hasta que toda la aplicación del navegador se cierra, o se libera la memoria cuando el/pestaña de la ventana está cerrada?

+1

¿Este código realmente podría causar pérdida de memoria? No entiendo porque. var elem = document.getElementById ('foo'); elem.myself = elem; – CEGRD

Respuesta

5

Probablemente no sea la pena reproducir todo el contenido de estos enlaces, así que te sugiero que hagas un poco de lectura y un vistazo a la other Google search hits:

javascript, circular references and memory leaks

Do you know what may cause memory leaks in JavaScript?

http://www.ibm.com/developerworks/web/library/wa-memleak/

http://www.ibm.com/developerworks/web/library/wa-sieve/index.html?ca=drs-

http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks

Las peores pérdidas de memoria son en IE6, donde las fugas son permanentes (incluso después de salir de la página web afectada). Las otras filtraciones generalmente son solo mientras estás en esa página específica y te limpian cuando sales de la página.

El hecho es que se supone que el navegador puede manejar referencias circulares. Se supone que es capaz de ver que a pesar de que un elemento DOM todavía se está refiriendo a un elemento JavaScript, el elemento JavaScript solo existe porque el elemento DOM aún está vivo y por lo tanto no hay una referencia externa verdadera al elemento DOM . Es este reconocimiento que las versiones anteriores de IE eran malas. Por lo tanto, en las referencias de código que involucran manejadores de eventos, el recolector de basura debe ser lo suficientemente inteligente como para saber que las únicas referencias que quedan del elemento DOM en JavaScript son referencias que desaparecerían cuando el elemento DOM y sus manejadores de eventos fueran eliminados. no hay referencias externas verdaderas por lo que es seguro eliminar tanto el elemento DOM como el manejador de eventos. Esta es una versión más complicada del problema de referencia circular general que todos los recolectores de basura deben manejar donde el objeto A se refiere al objeto B y el objeto B se refiere al objeto A, pero ningún otro objeto se refiere a A o B, por lo que ambos pueden liberarse .

jQuery's .data() hace las cosas más confiables porque las versiones anteriores de IE tenían un problema particular con las propiedades que se agregaron a un elemento DOM y no manejaba referencias circulares que involucraban los datos en esas propiedades y así no liberaría cosas cuando debería tener (una fuga). .data() funciona alrededor de eso usando solo una propiedad añadida en el elemento DOM que es una cadena segura y sin fugas. Esa cadena es entonces una clave en un objeto JavaScript que puede contener todas las propiedades que le gustaría asociar con el elemento DOM. Debido a que todas estas propiedades están almacenadas en JavaScript plano, donde los navegadores no tienen los errores de referencia circulares, hacerlo de esta manera no provoca fugas.

Es importante darse cuenta de que todavía puede haber algunas referencias circulares y eso está bien. El objetivo es mover las referencias circulares a un lugar que los navegadores manejen de forma adecuada en lugar de ubicarlas en el lugar donde los navegadores tienen errores.

+0

Así que IE6-7 no recoge correctamente las referencias circulares entre DOM y JS para las propiedades de expansión (que es lo que '.data' funciona). ¿Recoge correctamente las referencias para los controladores de eventos? –

+0

@joeyadams, eso creo, esa es mi opinión. – jfriend00

Cuestiones relacionadas