O draft da especificação ECMAScript 6 já trouxe muitas alegrias para os desenvolvedores modernos de JavaScript. Cobrimos algumas novas classes de coleções e loops de iteração for..of
em um post anterior. Neste post, vamos falar sobre algo que anda de mãos dadas com os loops for..of
: as funções gerador.
Há muitos materiais disponíveis que explicam o porquê e como usar geradores. Em resumo, os geradores são funções especiais que criam iteradores, e os iteradores são objetos que têm um método next()
, que pode ser chamado para receber um valor. Em uma função gerador, a palavra-chave yield
fornece o valor para next()
. O uso de yield
suspende a execução da função do gerador, preservando o estado até que next()
seja chamado novamente. Nesse ponto, o código é reiniciado e continua até yield
outro valor (ou até que a função do gerador seja encerrada). Há vários casos de uso canônicos para funções de gerador, como usá-las para iterar os números na sequência de Fibonacci.
Com os conceitos básicos definidos, vamos nos aprofundar em um exemplo de JavaScript que aborda alguns dos problemas de trabalhar com geradores. Há comentários extensos em todo o código, e você pode brincar com a versão ativa dele antes de ler:
Quais são as principais conclusões do código?
Primeiro, a criação de um gerador resulta em um iterador exclusivo com seu próprio estado distinto, e você pode transmitir parâmetros para o construtor do gerador que podem controlar o comportamento.
Em segundo lugar, é possível transmitir um parâmetro ao chamar o método next()
de um iterador. Esse valor será atribuído ao que estiver no lado esquerdo da instrução yield
da invocação de iterador anterior. Essa é uma ótima maneira de variar a saída do iterador. Aqui, usamos isso para controlar se a palavra gerada está em maiúsculas ou não. Se você quiser influenciar o primeiro valor gerado, faça isso usando um parâmetro para o construtor do gerador.
Por fim, os geradores podem produzir iteradores finitos ou infinitos. Se você estiver trabalhando com um iterador infinito, verifique se há algum tipo de condição terminal com base no valor yield
ed. É muito fácil escrever loops infinitos acidentalmente, especialmente ao usar for..of
para iteração. Se você estiver trabalhando com um iterador finito por meio de chamadas para next()
, a propriedade .done
do objeto retornado vai sinalizar se a iteração foi concluída.
Esperamos que este exemplo, junto com os outros recursos disponíveis na Web, gere um pouco de empolgação e faça você pensar em como usar geradores no seu próprio código. As versões do Firefox a partir da 31 e do Chrome a partir da 39 oferecem suporte a geradores de forma nativa. O projeto Regenerator oferece suporte a outros navegadores, e o uso do Traceur também é uma opção.
Agradecemos a Erik Arvidsson pela ajuda na revisão deste artigo.