La bozza della specifica ECMAScript 6 ha già regalato molte soddisfazioni agli sviluppatori JavaScript moderni. In un post precedente abbiamo trattato alcuni nuovi tipi di raccolte e cicli di iterazione for..of
. In questo post parleremo di un argomento che va di pari passo con i cicli for..of
: le funzioni generatore.
Esistono già molti materiali di qualità che spiegano il perché e il come utilizzare i generatori. In breve, i generatori sono funzioni speciali che creano iteratori e gli iteratori sono oggetti che dispongono di un metodo next()
, che può essere chiamato per ottenere un valore. All'interno di una funzione generatore, la parola chiave yield
fornisce il valore per next()
. L'utilizzo di yield
sospende l'esecuzione della funzione di generatore, preservando lo stato fino a quando next()
non viene richiamato di nuovo, a quel punto il codice si riavvia e continua finché non viene yield
un altro valore (o fino al termine della funzione di generatore). Esistono diversi casi d'uso canonici per le funzioni generatore, ad esempio utilizzarle per eseguire l'iterazione sui numeri della sequenza di Fibonacci.
Dopo aver chiarito le nozioni di base, esaminiamo in dettaglio un esempio di JavaScript che illustra alcuni dei problemi relativi all'utilizzo dei generatori. Sono presenti commenti dettagliati e puoi provare la versione live del codice prima di leggerlo:
Quali sono i punti chiave del codice?
Innanzitutto, la costruzione di un generatore genera un iteratore univoco con il proprio stato distinto e puoi passare parametri al costruttore del generatore che possono controllare il comportamento.
In secondo luogo, puoi passare un parametro quando chiami il metodo next()
di un iteratore e questo valore verrà assegnato a ciò che si trova sul lato sinistro dell'istruzione yield
dell'invocazione dell'iteratore precedente. Questo è un ottimo modo per variare l'output dell'iteratore: qui lo utilizziamo per controllare se la parola restituita è in maiuscolo o meno. Se vuoi influenzare il primo valore restituito, utilizza un parametro per il costruttore del generatore.
Infine, i generatori possono produrre iteratori finiti o infiniti. Se utilizzi un iteratore infinito, assicurati di avere una sorta di condizione di terminazione basata sul valore yield
ed: è molto facile scrivere accidentalmente cicli infiniti, soprattutto quando utilizzi for..of
per l'iterazione. Se utilizzi un iteratore finito tramite chiamate a next()
, la proprietà .done
dell'oggetto restituito indica se l'iterazione è completata.
Ci auguriamo che questo esempio, insieme alle altre risorse disponibili sul web, ti entusiasmi e ti induca a pensare a come utilizzare i generatori nel tuo codice. Le versioni di Firefox a partire dalla 31 e di Chrome a partire dalla 39 supportano i generatori in modo nativo. Il progetto Regenerator offre il supporto del generatore per altri browser e anche l'utilizzo di Traceur è un'opzione.
Grazie a Erik Arvidsson per l'aiuto fornito durante la revisione di questo articolo.