javascript - eliminar - Si se elimina un elemento DOM, ¿se eliminan también sus escuchas de la memoria?
insertar codigo html con jquery (6)
Navegadores modernos
JavaScript simple
Si un elemento DOM que se elimina no tiene referencias (no hay referencias que lo indiquen), entonces sí : el recolector de basura recoge el elemento en sí, así como cualquier controlador / detector de eventos asociado.
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 aún apuntan a dicho elemento, el elemento y sus escuchas de eventos se conservan 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án exactamente de la misma manera (considerando 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 que, en teoría, podría cambiarse en cualquier momento) llamado cleanData()
(aquí es cómo se ve este método ) que limpia automáticamente todos los datos / eventos asociados con un elemento al eliminarlos. desde el DOM (ya sea a través de. remove()
, empty()
, html("")
etc).
Navegadores antiguos
Se sabe que los navegadores más antiguos, específicamente las versiones más antiguas de IE, tienen problemas de pérdida de memoria debido a que los oyentes de eventos mantienen referencias a los elementos a los que estaban conectados.
Si desea una explicación más detallada de las causas, los patrones y las soluciones que se usan para corregir las fugas de memoria de la versión de IE heredada, le recomiendo que lea este artículo de MSDN sobre Entender y resolver los patrones de fugas de Internet Explorer.
Algunos artículos más relevantes para esto:
La eliminación manual de los oyentes probablemente sería un buen hábito en este caso (solo si la memoria es tan vital para su aplicación y en realidad está apuntando a dichos navegadores).
Si se elimina un elemento DOM, ¿se eliminan también sus escuchas de la memoria?
Con respecto a jQuery
, los siguientes métodos comunes también eliminarán otras construcciones, como los controladores de datos y eventos:
Además de los elementos en sí, se eliminan todos los eventos enlazados y los datos jQuery asociados con los elementos.
Para evitar pérdidas de memoria, jQuery elimina otras construcciones, como los controladores de datos y eventos, de los elementos secundarios antes de eliminar los elementos.
Además, jQuery elimina otras construcciones, como los controladores de datos y eventos, de elementos secundarios antes de reemplazar esos elementos con el nuevo contenido.
No dude en ver el montón para ver las fugas de memoria en los controladores de eventos manteniendo una referencia al elemento con un cierre y el elemento manteniendo una referencia al controlador de eventos.
El 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 manejador. Y el manejador 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 desechado al anular la referencia a la misma desde tu colección. => todo el objeto y todo lo que hace referencia permanecerán en la memoria hasta que la página salga. => tienes que pensar en un método de eliminación completo para tu clase de objeto o confiar en un marco mvc por ejemplo.
Además, no dude en utilizar la parte del árbol de retención de las herramientas de desarrollo de Chrome.
Sí, el recolector de basura los eliminará también. Aunque no siempre puede ser el caso con los navegadores heredados.
Solo extendiendo otras respuestas ...
Los controladores de eventos delegados no se eliminarán al eliminar el elemento.
$(''body'').on(''click'', ''#someEl'', function (event){
console.log(event);
});
$(''#someEL'').remove(); // removing the element from DOM
Revisa ahora:
$._data(document.body, ''events'');
con respecto a jQuery:
El método .remove () saca elementos del DOM. Utilice .remove () cuando desee eliminar el elemento en sí, así como todo lo que contenga. Además de los elementos en sí, se eliminan todos los eventos enlazados y los datos jQuery asociados con los elementos. Para eliminar los elementos sin eliminar datos y eventos, use .detach () en su lugar.
Referencia: http://api.jquery.com/remove/
jQuery v1.8.2 .remove()
código fuente:
remove: function( selector, keepData ) {
var elem,
i = 0;
for ( ; (elem = this[i]) != null; i++ ) {
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
}
return this;
}
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 detectores de eventos pueden eliminarse, pero el node
todavía existe en la memoria.