Chiusure e handler?
C'è un campo in cui è necessario soffermarsi sull'applicazione delle chiusure: le funzioni che gestiscono eventi in Javascript, ovvero i così detti handler. Partiamo da un problema reale, e vediamo come viene affrontato tramite le chiusure. In una pagina HTML ci sono due elementi: uno spazio in cui l'utente può scrivere qualcosa (un banale elemento INPUT di tipo text) e un bottone. Alla pressione del bottone Javascript fa partire un timer, che dopo dieci secondi mostrerà un alert che visualizza cosa c'era scritto nell'INPUT al momento in cui l'utente aveva premuto il tasto. Eccovi l'esempio funzionante.
L'utente potrebbe ad esempio scrivere hello e premere il tasto, poi scrivere world e premere il tasto. Dopo alcuni secondi vedrebbe in successione due alert, uno in cui è scritto hello e l'altro in cui è scritto world. Per implementare un tale programma qualcuno potrebbe essere tentato di scrivere qualcosa come:
function whenButtonIsPressed() { setTimeout(showAlert, 10000); } function showAlert() { var e = object.getElementById("inputobj"); alert(e.value); }
Nell'esempio immaginiamo che il bottone abbia un evento onClick che richiama la funzione whenButtonIsPressed e che il testo digitato dall'utente sia contenuto in un elemento INPUT con ID inputobj.
Ovviamente il codice mostrato sopra non funziona, perchè l'handler del timer, ovvero la funzione showAlert, va a leggere il contenuto dell'INPUT solo quando deve visualizzare l'alert. Se nel mentre il contenuto è cambiato perchè l'utente nel corso dei 10 secondi ha scritto qualcosa di nuovo il nostro gioco non funziona. Noi vogliamo che alla pressione del tasto, l'alert risultante 10 secondi dopo visualizzi quello che c'era scritto quando il tasto era stato premuto. Ci servirebbe un handler che ha memoria del passato... ovvero, una chiusura! Ecco il codice corretto:
function whenButtonIsPressed() { var string = document.getElementById("inputobj").value; var myHandler = function() { alert(string); }; setTimeout(myHandler, 10000); }
Abbiamo risolto il problema con un'unica funzione. La chiusura che usiamo come handler ha un riferimento a string, dunque si crea un collegamento tra l'oggetto che conteneva tale variabile al momento della creazione della funzione e la funzione stessa.
Nota: questo particolare problema potrebbe essere
risolto anche tramite eval(), ma ci sono molti casi in cui le chiusure
risolvono problemi non risolvibili con eval() e tantissimi altri casi in cui
risolvono i problemi in maniera molto più elegante.