8

Supongamos que he adjuntado una variedad de detectores de eventos a varios elementos de formulario. Más tarde, quiero eliminar todo el formulario.¿Es necesario eliminar los detectores de eventos de JavaScript antes de eliminar el elemento al que están conectados?

¿Es necesario (o sugerido) anular el registro de cualquier controlador de eventos que exista en el formulario y sus elementos? Si es así, ¿cuál es la forma más fácil de eliminar a todos los oyentes en una colección de elementos? ¿Cuáles son las repercusiones de no hacerlo? Estoy usando Prototype, si es importante.

Esto es lo que estoy haciendo en realidad. Tengo una forma simple, así:

<form id="form"> 
    <input type="text" id="foo"/> 
    <input type="text" id="bar"/> 
</form> 

observo varios eventos en las entradas, por ejemplo:

$('foo').observe('keypress', onFooKeypress); 
$('bar').observe('keypress', onBarKeypress); 

etc.

El formulario se envía a través de AJAX y la respuesta es una nueva copia del formulario. Sustituyo el formulario antiguo con una copia del nuevo haciendo algo como $('form').replace(newForm). ¿Estoy acumulando un montón de evento cruft?

Respuesta

3

Sí, un poco. No es suficiente para ser un gran problema, pero las versiones anteriores de IE se filtrarán en esas circunstancias.

A partir del prototipo 1.6.1 (actualmente en su versión final candidata), la biblioteca se encarga de esta limpieza en la descarga de la página. Cuando usa Prototype para agregar un observador de evento, mantiene una referencia a ese elemento en una matriz; en la descarga de la página, recorre esa matriz y elimina a todos sus observadores.

Sin embargo, si el usuario va a permanecer en esta página por un tiempo, el uso de memoria se acumulará durante la vida de la página. Tiene varias opciones:

  1. detectar eventos en un ancestro de la forma, uno que nunca se reemplazó. Luego, en su controlador, ver de dónde vino el evento. (es decir, "delegación de eventos")

  2. Anule el registro de todas sus llamadas antes de llamar al Element#replace. En su ejemplo, que haría:

    $('foo', 'bar').each(Element.stopObserving); 
    

Esto es equivalente a llamar stopObserving sin argumentos, que tiene el efecto de eliminar todos los manipuladores en un elemento dado.

Yo recomendaría la opción 1.

(Hemos hablado de hacer la extracción automática oyente en una versión futura de Prototype como parte de Element#update y Element#replace, pero es una solución de compromiso rendimiento.)

4

Es posible que los eventos que no estén sin registrar no liberen su memoria automáticamente. Esto es especialmente un problema en versiones anteriores de IE.

El prototipo solía tener un sistema automático de recolección de basura para esto, pero el método se ha eliminado en la versión 1.6. Está documentado here. Ya sea que la eliminación del método signifique que la recolección de basura ya no se lleva a cabo, o que el método simplemente ya no está a disposición del público, no lo sé. También tenga en cuenta que solo se solicitó en la descarga de la página, lo que significa que si los usuarios permanecen en la misma página durante mucho tiempo mientras realizan muchas actualizaciones de AJAX y DOM, la memoria puede perder hasta un grado inaceptable incluso durante esa visita de una página.

0

Siempre es bueno eliminar los detectores de eventos de los elementos que se eliminan del DOM en el caso del escenario que Jonas menciona a continuación.

Cuestiones relacionadas