Si se elimina un elemento DOM, ¿también se eliminan sus oyentes de la memoria?
fuente
Si se elimina un elemento DOM, ¿también se eliminan sus oyentes de la memoria?
JavaScript simple
Si un elemento DOM que se elimina no tiene referencias (no hay referencias que lo señalen), entonces sí , el elemento en sí es recogido por el recolector de basura, así como por cualquier controlador / escucha de eventos asociado con él.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
b = null;
// A reference to 'b' no longer exists
// Therefore the element and any event listeners attached to it are removed.
Sin embargo; Si hay referencias que todavía apuntan a dicho elemento, el elemento y sus oyentes de eventos se retienen en la memoria.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
// A reference to 'b' still exists
// Therefore the element and any associated event listeners are still retained.
jQuery
Sería justo suponer que los métodos relevantes en jQuery (como remove()
) funcionarían exactamente de la misma manera (considerando que remove()
se escribió usando, removeChild()
por ejemplo).
Sin embargo, esto no es cierto ; la biblioteca jQuery en realidad tiene un método interno (que no está documentado y en teoría podría cambiarse en cualquier momento) llamado cleanData()
(así es como se ve este método ) que limpia automáticamente todos los datos / eventos asociados con un elemento al eliminarlo del DOM (ya sea a través de este. remove()
, empty()
, html("")
etc).
Se sabe que los navegadores más antiguos, específicamente las versiones anteriores de IE, tienen problemas de pérdida de memoria debido a que los oyentes de eventos mantienen referencias a los elementos a los que se adjuntaron.
Si desea una explicación más detallada de las causas, los patrones y las soluciones utilizadas para corregir las pérdidas de memoria de la versión IE heredada, le recomiendo que lea este artículo de MSDN sobre Comprender y resolver patrones de fugas de Internet Explorer.
Algunos artículos más relevantes para esto:
Eliminar manualmente los oyentes probablemente sea un buen hábito en este caso (solo si la memoria es tan vital para su aplicación y realmente está apuntando a tales navegadores).
remove
método. la mayoría de las veces el DOM simplemente se borrará por completo. (como enlaces turbo o algo así). Me pregunto cómo se ve afectada la memoria si lo hagodocument.body.innerHTML = ''
...con respecto a jQuery:
Referencia: http://api.jquery.com/remove/
Código
.remove()
fuente de jQuery v1.8.2 :aparentemente jQuery usa
node.removeChild()
De acuerdo con esto: https://developer.mozilla.org/en-US/docs/DOM/Node.removeChild ,
The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.
es decir, los oyentes de eventos pueden ser eliminados, pero
node
aún existe en la memoria.fuente
removeChild
no lo haría. Ambos también le devuelven una referencia que puede mantener para volver a unir este último (en cuyo caso, obviamente, permanece en la memoria) o tirar (en cuyo caso finalmente es recogido por GC y eliminado).No dude en ver el montón para ver pérdidas de memoria en los controladores de eventos que mantienen una referencia al elemento con un cierre y el elemento que mantiene una referencia al controlador de eventos.
Al recolector de basura no le gustan las referencias circulares.
Caso habitual de pérdida de memoria: admitir que un objeto tiene una referencia a un elemento. Ese elemento tiene una referencia al controlador. Y el controlador tiene una referencia al objeto. El objeto tiene referencias a muchos otros objetos. Este objeto era parte de una colección que crees que has tirado al no hacer referencia a ella desde tu colección. => todo el objeto y todo lo que hace referencia permanecerá en la memoria hasta que salga la página. => debe pensar en un método de eliminación completo para su clase de objeto o confiar en un marco de mvc, por ejemplo.
Además, no dude en utilizar la parte del árbol de retención de las herramientas de desarrollo de Chrome.
fuente
Solo extendiendo otras respuestas ...
Los controladores de eventos delegados no se eliminarán al eliminar elementos.
Revisa ahora:
fuente
En cuanto a
jQuery
, los siguientes métodos comunes también eliminarán otras construcciones, como los controladores de datos y eventos:eliminar()
vacío()
html ()
fuente
Sí, el recolector de basura también los eliminará. Sin embargo, no siempre puede ser el caso con los navegadores heredados.
fuente