Une fois sur un écouteur d'événements

Petite question: à quoi sert le troisième paramètre transmis à addEventListener() ?

Ne vous sentez pas gêné si vous pensiez que addEventListener() ne prenait que deux paramètres, ou si vous codifiez toujours une valeur de false, avec une vague idée qu'elle a quelque chose à voir avec… des bulles ?

addEventListener() plus configurable

La méthode addEventListener() a parcouru un long chemin depuis les débuts du Web, et sa nouvelle fonctionnalité est configurée via une version surpuissante de ce troisième paramètre. Les modifications récentes apportées à la définition de la méthode permettent aux développeurs de fournir des options supplémentaires via un objet de configuration, tout en restant rétrocompatibles lorsqu'il existe un paramètre booléen ou qu'une option n'est pas spécifiée.

Nous sommes heureux d'annoncer que Chrome 55 prend en charge l'option once dans cet objet de configuration, ainsi que les options passive (implémentée dans Chrome 51) et capture (implémentée dans Chrome 49). Exemple :

element.addEventListener('click', myClickHandler, {
    once: true,
    passive: true,
    capture: true
});

Vous pouvez combiner ces options en fonction de votre cas d'utilisation.

Avantages de nettoyer après vous

Voici la syntaxe à utiliser pour la nouvelle option once, mais à quoi cela vous sert-il ? En bref, il vous fournit un écouteur d'événements adapté aux cas d'utilisation "fini".

Par défaut, les écouteurs d'événements persistent après la première fois qu'ils sont appelés, ce qui est ce que vous souhaitez pour certains types d'événements (boutons sur lesquels vous pouvez cliquer plusieurs fois, par exemple). Toutefois, pour d'autres utilisations, il n'est pas nécessaire de conserver un écouteur d'événements, et cela peut entraîner un comportement indésirable si vous disposez d'un rappel qui ne doit s'exécuter qu'une seule fois. Les développeurs hygiénistes ont toujours eu la possibilité d'utiliser removeEventListener() pour nettoyer explicitement les choses, en suivant des modèles tels que:

element.addEventListener('click', function cb(event) {
    // ...one-time handling of the click event...
    event.currentTarget.removeEventListener(event.type, cb);
});

Le code équivalent, qui utilise le nouveau paramètre once, est plus clair et ne vous oblige pas à suivre le nom de l'événement (event.type, dans l'exemple précédent) ni une référence à la fonction de rappel (cb):

element.addEventListener('click', function(event) {
    // ...one-time handling of the click event...
}, {once: true});

Nettoyer vos gestionnaires d'événements peut également offrir des gains d'efficacité en termes de mémoire en détruisant le champ d'application associé à la fonction de rappel, ce qui permet de collecter les déchets de toutes les variables capturées dans ce champ d'application. Voici un exemple où cela peut faire la différence:

function setUpListeners() {
    var data = ['one', 'two', '...etc.'];

    window.addEventListener('load', function() {
    doSomethingWithSomeData(data);
    // data is now part of the callback's scope.
    });
}

Par défaut, le rappel de l'écouteur d'événements load reste dans le champ d'application une fois l'exécution terminée, même s'il n'est plus jamais utilisé. Étant donné que la variable data est utilisée dans le rappel, elle restera également dans le champ d'application et ne sera jamais collectée par le garbage collector. Toutefois, si le rappel a été supprimé via le paramètre once, la fonction elle-même et tout ce qui est maintenu en vie via son champ d'application peuvent être candidats au garbage collection.

Prise en charge des navigateurs

Chrome 55 et versions ultérieures, Firefox 50 et versions ultérieures, et la version preview technologique 7 et ultérieures de Safari sont compatibles nativement avec l'option once.

De nombreuses bibliothèques d'UI JavaScript fournissent des méthodes pratiques pour créer des écouteurs d'événements. Certaines disposent de raccourcis pour définir des événements ponctuels, dont la plus notable est la méthode one() de jQuery. Un polyfill est également disponible dans la bibliothèque dom4 d'Andrea Giammarchi.

Merci

Merci à Ingvar Stepanyan pour ses commentaires sur l'exemple de code de cet article.