Pregunta sorpresa: ¿Cuál es el propósito del tercer parámetro que se pasa a addEventListener()
?
No te avergüences si pensaste que addEventListener()
solo tomaba dos parámetros, o tal vez siempre codificaste un valor de false
, con la vaga idea de que tiene algo que ver con… ¿burbujas?
Un addEventListener() más configurable
El método addEventListener()
ha recorrido un largo camino desde los primeros días de la
Web, y su nueva funcionalidad se configura a través de una versión mejorada de ese
tercer parámetro. Los cambios recientes en la definición del método permiten a los desarrolladores proporcionar opciones adicionales a través de un objeto de configuración, a la vez que mantienen la retrocompatibilidad cuando hay un parámetro booleano o cuando no se especifica una opción.
Nos complace anunciar que Chrome 55 agrega compatibilidad con la opción once
en ese objeto de configuración, junto con las opciones passive
(implementada en Chrome 51) y capture
(implementada en Chrome 49). Por ejemplo:
element.addEventListener('click', myClickHandler, {
once: true,
passive: true,
capture: true
});
Puedes combinar esas opciones según corresponda a tu caso de uso.
Los beneficios de limpiar después de ti
Esa es la sintaxis para usar la nueva opción once
, pero ¿qué te brinda? En resumen, te brinda un objeto de escucha de eventos que se adapta a los casos de uso de "todo en uno".
De forma predeterminada, los objetos de escucha de eventos persisten después de la primera vez que se los llama, lo que es lo que deseas para algunos tipos de eventos, por ejemplo, botones en los que se puede hacer clic varias veces. Sin embargo, para otros usos, no es necesario tener un objeto de escucha de eventos y puede generar un comportamiento no deseado si tienes una devolución de llamada que solo se debe ejecutar una vez. Los desarrolladores higiénicos siempre tuvieron la opción de usar removeEventListener()
para limpiar de forma explícita, siguiendo patrones como los siguientes:
element.addEventListener('click', function cb(event) {
// ...one-time handling of the click event...
event.currentTarget.removeEventListener(event.type, cb);
});
El código equivalente, que usa el nuevo parámetro once
, es más claro y no te obliga a hacer un seguimiento del nombre del evento (event.type
, en el ejemplo anterior) ni de una referencia a la función de devolución de llamada (cb
):
element.addEventListener('click', function(event) {
// ...one-time handling of the click event...
}, {once: true});
Limpiar los controladores de eventos también puede ofrecer eficiencias de memoria, ya que destruye el alcance asociado con la función de devolución de llamada, lo que permite que se recopilen las variables capturadas en ese alcance. Este es un ejemplo en el que haría una diferencia:
function setUpListeners() {
var data = ['one', 'two', '...etc.'];
window.addEventListener('load', function() {
doSomethingWithSomeData(data);
// data is now part of the callback's scope.
});
}
De forma predeterminada, la devolución de llamada del objeto de escucha de eventos load
permanecerá en el alcance cuando termine de ejecutarse, aunque nunca se vuelva a usar. Debido a que la variable data
se usa dentro de la devolución de llamada, también permanecerá en el alcance y nunca se recogerá la basura. Sin embargo, si se quitara la devolución de llamada a través del parámetro once
, tanto la función en sí como todo lo que se mantenga activo a través de su alcance podrían ser candidatos para la recolección de basura.
Navegadores compatibles
Chrome 55 y versiones posteriores, Firefox 50 y versiones posteriores, y la versión preliminar de tecnología 7 y versiones posteriores de Safari tienen compatibilidad nativa con la opción once
.
Muchas bibliotecas de la IU de JavaScript proporcionan métodos convenientes para crear objetos de escucha de eventos, y algunas tienen atajos para definir eventos únicos, el más notable de los cuales es el método one()
de jQuery. También hay disponible un polyfill, como parte de la biblioteca dom4
de Andrea Giammarchi.
Gracias
Gracias a Ingvar Stepanyan por los comentarios sobre el código de muestra de esta publicación.