Si tengo un elemento principal con elementos secundarios que tienen detectores de eventos vinculados a ellos, ¿necesito eliminar esos detectores de eventos antes de borrar el elemento primario? (es decir, parent.innerHTML = '';
) ¿Podría haber pérdidas de memoria si los detectores de eventos no están separados de un elemento si se eliminan del DOM?¿Debo eliminar los detectores de eventos antes de eliminar los elementos?
Respuesta
Respuesta corta: sí
Respuesta larga: La mayoría de los navegadores manejan esto correctamente y eliminar esos manipuladores de sí mismos. Hay algunos navegadores más antiguos (IE 6 y 7, si no recuerdo mal) que están estropeando esto. Sí, podría haber pérdidas de memoria. No deberías tener que preocuparte por esto, pero debes hacerlo. Eche un vistazo al this document.
Solo para actualizar la información aquí. He estado probando varios navegadores, específicamente para fugas de memoria para receptores de eventos dependientes circularmente en eventos de carga iframe.
El código utilizado (jsFiddle interfiere con las pruebas de memoria, a fin de utilizar su propio servidor para probar esto):
<div>
<label>
<input id="eventListenerCheckbox" type="checkbox" /> Clear event listener when removing iframe
</label>
<div>
<button id="startTestButton">Start Test</button>
</div>
</div>
<div>
<pre id="console"></pre>
</div>
<script>
(function() {
var consoleElement = document.getElementById('console');
window.log = function(text) {
consoleElement.innerHTML = consoleElement.innerHTML + '<br>' + text;
};
}());
(function() {
function attachEvent(element, eventName, callback) {
if (element.attachEvent)
{
element.attachEvent(eventName, callback);
}
else
{
element[eventName] = callback;
}
}
function detachEvent(element, eventName, callback) {
if (element.detachEvent)
{
element.detachEvent(eventName, callback);
}
else
{
element[eventName] = null;
}
}
var eventListenerCheckbox = document.getElementById('eventListenerCheckbox');
var startTestButton = document.getElementById('startTestButton');
var iframe;
var generatedOnLoadEvent;
function createOnLoadFunction(iframe) {
var obj = {
increment: 0,
hugeMemory: new Array(100000).join('0') + (new Date().getTime()),
circularReference: iframe
};
return function() {
// window.log('iframe onload called');
obj.increment += 1;
destroy();
};
}
function create() {
// window.log('create called');
iframe = document.createElement('iframe');
generatedOnLoadEvent = createOnLoadFunction(iframe);
attachEvent(iframe, 'onload', generatedOnLoadEvent);
document.body.appendChild(iframe);
}
function destroy() {
// window.log('destroy called');
if (eventListenerCheckbox.checked)
{
detachEvent(iframe, 'onload', generatedOnLoadEvent)
}
document.body.removeChild(iframe);
iframe = null;
generatedOnLoadEvent = null;
}
function startTest() {
var interval = setInterval(function() {
create();
}, 100);
setTimeout(function() {
clearInterval(interval);
window.log('test complete');
}, 10000);
}
attachEvent(startTestButton, 'onclick', startTest);
}());
</script>
Si no hay pérdida de memoria, la memoria utilizada se incrementará en torno a 1000kb o menos después de la las pruebas se ejecutan. Sin embargo, si hay una pérdida de memoria, la memoria aumentará en aproximadamente 16,000kb. La eliminación del detector de eventos primero siempre da como resultado un menor uso de memoria (sin pérdidas).
Resultados:
- IE6 - Pérdida de memoria
- IE7 - Pérdida de memoria
- IE8 - fugas sin memoria
- IE9 - pérdida de memoria (???)
- IE10 - pérdida de memoria (???)
- IE11 - sin pérdida de memoria
- Edge (20) - sin pérdida de memoria
- Chrome (50) - sin pérdida de memoria
- Firefox (46) - difícil de decir, no gotea mal, entonces ¿tal vez solo un recolector de basura ineficaz? Termina con 4MB extra sin razón aparente.
- Opera (36) - no hay pérdida de memoria
- Safari (9) - fugas sin memoria
Conclusión: Sangrado aplicaciones de extremo probablemente puede salirse con la no eliminación de los detectores de eventos. Pero aún así lo consideraría una buena práctica, a pesar de la molestia.
- 1. ¿Es necesario eliminar los detectores de eventos de JavaScript antes de eliminar el elemento al que están conectados?
- 2. ¿Hay alguna manera de eliminar los detectores de eventos desconocidos de los objetos?
- 3. ¿Debo eliminar las suscripciones a eventos de los objetos antes de que queden huérfanos?
- 4. Jquery detectores de eventos añadiendo a los elementos
- 5. ¿Cómo eliminar todos los detectores de eventos de un objeto de visualización?
- 6. Eliminar todos los elementos de una lista
- 7. Cómo eliminar todos los detectores de eventos a la vez en AS3
- 8. ¿Debo eliminar un controlador de eventos?
- 9. ¿Quitar todos los detectores de eventos JavaScript de un elemento y sus elementos secundarios?
- 10. ¿Cómo eliminar todos los elementos de ListBox?
- 11. Eliminar todos los elementos dentro de linearlayout
- 12. Cambie los elementos de 2 html y preserve los detectores de eventos en ellos
- 13. ¿Debo desvincular el evento jquery antes de eliminar el elemento?
- 14. ¿Debo eliminar explícitamente los depósitos SWT?
- 15. ¿Los detectores de eventos en jQuery se eliminan automáticamente cuando quita el elemento con .html()?
- 16. css: cómo eliminar pseudo elementos (después, antes, ...)
- 17. ¿Debo deshacerme de los eventos?
- 18. ¿Qué debo hacer antes de eliminar elementos en un vector de punteros a objetos asignados dinámicamente?
- 19. Eliminar espacios iniciales y finales de los elementos XML
- 20. ¿Eliminar todos los elementos vacíos de un hash/YAML?
- 21. C# - Lista - eliminar todos los elementos pero NO los primeros
- 22. Anulación toString para eliminar los espacios entre los elementos
- 23. ¿Debo eliminar este tipo de controlador de eventos?
- 24. Cómo deshabilitar temporalmente los detectores de eventos en Swing?
- 25. PHP eliminar todos los caracteres antes de cadena específica
- 26. Cómo eliminar todos los controladores de eventos Click en Jquery
- 27. ¿Cómo eliminar todos los controladores de eventos Click?
- 28. ¿Debo eliminar TestFlight antes de enviarme a la App Store?
- 29. ¿Cómo puedo eliminar los elementos del script antes de que se ejecuten?
- 30. ¿Cómo debo eliminar todos los elementos de un NSTableView controlado por NSArrayController?
De hecho: aunque la mayoría de los navegadores actuales no sufrirán tanto, IE 7 todavía se usa comúnmente. También eche un vistazo a [Patrones de fuga de memoria en JavaScript] (http://www.ibm.com/developerworks/web/library/wa-memleak/). –
¿Hay alguien lo suficientemente experto como para actualizar esto para el mercado actual de los navegadores? ¿O vale la pena una pregunta por separado? IE7, pensé, fue [prácticamente eliminado] (http://theie7countdown.com/), mientras que [ie8] (http://theie8countdown.com/) sigue dando vueltas. ¿IE8 maneja los oyentes de eventos abandonados? –
6 años después, creo que 'IE <10' se puede considerar obsoleto y no utilizado por nadie que vaya a sitios que no sean Yahoo y AOL en este momento.Cualquiera que use IE de forma no-lógica en este punto probablemente sea más propenso a ser víctima de una estafa telefónica de un indio o de tener un virus que tener problemas con los manejadores de eventos que desaceleren su cangrejo de navegador. –