style que manipular elementos attribute atributos aprender javascript internet-explorer memory-leaks garbage-collection circular-reference

javascript - que - title css



DOM: ¿por qué es esto una pérdida de memoria? (4)

Considere esta cita de las filtraciones de memoria de Mozilla Docs sobre JavaScript :

function addHandler() { var el = document.getElementById(''el''); el.onclick = function() { this.style.backgroundColor = ''red''; } }

El código anterior configura el elemento para que se vuelva rojo cuando se presiona. También crea una pérdida de memoria. ¿Por qué? Debido a que la referencia a el se captura inadvertidamente en el cierre creado para la función interna anónima. Esto crea una referencia circular entre un objeto JavaScript (la función) y un objeto nativo (el).

Por favor, explique las razones anteriores de fuga de una manera simple y concisa, no estoy obteniendo el punto exacto.

¿El sitio / página enfrenta un problema de seguridad debido a la fuga? ¿Cómo los evito? ¿Qué otro código puede causar pérdidas de memoria? ¿Cómo puedo saber cuándo se produjo una pérdida de memoria?

Soy un principiante absoluto para el tema de las pérdidas de memoria. ¿Podría alguien aclararme estas cosas paso a paso? También alguien me puede ayudar a aclarar esta afirmación "Esto crea una referencia circular entre un objeto JavaScript (la función) y un objeto nativo (el)".


Consulte también la sección de más información del artículo de MS sobre el tema:

Esta pérdida de memoria se produce porque los objetos DOM no son objetos de JScript. Los objetos DOM no están en el esquema de recolección de elementos no utilizados de JScript. Por lo tanto, la referencia circular entre los objetos DOM y los manejadores de JScript no se romperá hasta que el navegador elimine por completo la página.

pero tenga en cuenta que, a diferencia de lo que se afirma en ese artículo (la memoria se recuperará cuando el navegador vaya a una página nueva), este artículo confirma que un error en IE 6 hizo que la memoria se filtrara para siempre.


Hay dos conceptos que lo ayudarán a comprender este ejemplo.

1) cierres

La definición de un cierre es que cada función interna tiene acceso a las variables y parámetros de función de sus padres.

Cuando la función addHandler() finaliza, la función anónima aún tiene acceso a la variable padre principal.

2) Funciones = memoria

Cada vez que define una function se crea un nuevo objeto. Lo que hace que este ejemplo sea un poco confuso es que onclick es un evento que solo se puede establecer en un elemento DOM una vez.

Entonces seguramente el.onclick = function(){}; simplemente sobrescribirá la función anterior ¿verdad?

¡Incorrecto! cada vez que se ejecuta addHandler, se crea un nuevo objeto de función.

En conclusión:

Cada vez que se ejecuta la función creará un nuevo objeto, con un cierre que contiene el . Viendo que la función anónima mantiene el acceso a el , el recolector de basura no puede eliminarlo de la memoria.

La función anon mantendrá acceso a el, y el tiene acceso a la función, que es una referencia circular, que causa una pérdida de memoria en IE.


La administración de memoria de JavaScript generalmente funciona de la siguiente manera: "mientras sea posible alcanzarla, guárdela". Este es básicamente el paradigma que está detrás de cualquier modelo de memoria impulsado por recolección de basura.

Los recolectores de basura tienden a ser muy buenos en lo que hacen, incluso detectan si un determinado grupo de elementos solo es accesible dentro de este mismo grupo de elementos. A esos grupos también se les llama referencia circular, ya que si sigues las referencias terminarás en un elemento que ya has visitado: has corrido un círculo.

Sin embargo, en tu ejemplo, en realidad tienes dos objetos de dos "mundos" diferentes:

Internet Explorer usa su propio esquema de recolección de basura para esto, separado del mecanismo utilizado por JavaScript. Es la interacción entre los dos que puede causar pérdidas de memoria.

Y esto es exactamente lo que sucede y puede causar pérdidas de memoria.


Siempre que defina una función en JavaScript, se crea un contexto de ejecución para ella; este contexto de ejecución contiene referencias a todas las variables en la cadena de alcance, comenzando desde el alcance global hasta el alcance local:

function test() { var el = document.getElementById(''el''); el.onclick = function() { // execution context of this function: el, test alert(''hello world''); } }

Cuando se realiza la test() , la función anónima no se recicla aún porque ahora está asignada a un elemento del DOM; es decir, está siendo referenciado por una propiedad del elemento DOM.

Al mismo tiempo, el elemento DOM también es parte del contexto de ejecución de la función y ahora no se puede reciclar debido a la referencia cíclica, aunque no es inmediatamente obvio que se usa realmente; puedes encontrar una demostración de eso en esta respuesta .

Dicho esto, hoy en día, la mayoría de los motores de JavaScript (incluso los que se encuentran en IE) utilizan un recolector de basura más avanzado que puede identificar las variables no utilizadas mucho mejor, utilizando técnicas como la recolección de basura generacional / efímera mark-and-sweep .

Para asegurarse de que no se encuentre con problemas en ningún navegador (sin embargo, debido a la vida útil típica de una página, esto es principalmente teórico):

document.getElementById(''el'').onclick = function() { alert(''hello world''); }