Un listener di eventi

Jacopo Posnick
Jacopo Posnick

Quiz: a cosa serve il terzo parametro passato a addEventListener()?

Non ti imbarazzare se pensavi che addEventListener() prendesse solo due parametri, o magari solo codificasse sempre un valore false in modo vago, con la vaga comprensione che ha a che fare con... le bolle?

Una funzione =() più configurabile

Il metodo addEventListener() ha fatto molta strada dagli albori del web e la sua nuova funzionalità è configurata tramite una versione potenziata di questo terzo parametro. Le recenti modifiche alla definizione del metodo consentono agli sviluppatori di fornire opzioni aggiuntive tramite un oggetto di configurazione, pur rimanendo compatibile con le versioni precedenti quando è presente un parametro booleano o quando un'opzione non è specificata.

Siamo lieti di annunciare che Chrome 55 aggiunge il supporto per l'opzione once nell'oggetto di configurazione, insieme alle opzioni passive (implementate in Chrome 51) e capture (implementate in Chrome 49). Ad esempio:

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

Puoi combinare queste opzioni per adattarle al tuo caso d'uso.

I vantaggi di pulire la casa

Questa è la sintassi per usare la nuova opzione once, ma cosa ottieni? In breve, offre un listener di eventi su misura per i casi d'uso "one and done".

Per impostazione predefinita, i listener di eventi rimangono persistenti dopo la prima chiamata, ovvero ciò che vuoi per alcuni tipi di eventi, ad esempio pulsanti su cui è possibile fare clic più volte. Per altri utilizzi, tuttavia, non è necessario mantenere un listener di eventi e può portare a comportamenti indesiderati se si dispone di un callback che deve essere eseguito una sola volta. Gli sviluppatori di soluzioni igieniche hanno sempre avuto la possibilità di usare removeEventListener() per ripulire esplicitamente le cose, seguendo pattern come:

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

Il codice equivalente, che utilizza il nuovo parametro once, è più chiaro e non obbliga a tenere traccia del nome dell'evento (event.type, nell'esempio precedente) o di un riferimento alla funzione di callback (cb):

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

La pulizia dei gestori di eventi può anche offrire efficienze di memoria eliminando l'ambito associato alla funzione di callback, consentendo la garbage collection di qualsiasi variabile acquisita in quell'ambito. Ecco un esempio in cui può fare la differenza:

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

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

Per impostazione predefinita, il callback del listener di eventi load rimarrà nell'ambito al termine dell'esecuzione, anche se non viene mai utilizzato di nuovo. Poiché la variabile data viene utilizzata all'interno del callback, rimarrà nell'ambito e non verrà mai recuperata. Tuttavia, se il callback è stato rimosso tramite il parametro once, sia la funzione stessa sia tutto ciò che viene mantenuto attivo tramite il relativo ambito saranno potenzialmente candidati per la garbage collection.

Supporto del browser

Chrome 55 e versioni successive, Firefox 50 e versioni successive e l'anteprima della tecnologia 7 e versioni successive di Safari prevedono il supporto nativo per l'opzione once.

Molte librerie dell'interfaccia utente di JavaScript offrono metodi pratici per la creazione di ascoltatori di eventi e alcune hanno scorciatoie per definire eventi una tantum, il più degno di nota è il metodo one() di jQuery. È inoltre disponibile un polyfill, parte della libreria dom4 di Andrea Giammarchi.

Grazie per aver deciso

Grazie a Ingvar Stepanyan per il feedback sul codice campione in questo post.