Générateurs : les bits gourmands en ressources

Le brouillon de spécification d'ECMAScript 6 a déjà généré de nombreuses sources de plaisir pour le développeur JavaScript moderne. Nous avons abordé les nouvelles classes de collections et les boucles d'itération for..of dans un article précédent. Dans cet article, nous allons parler d'un élément qui va de pair avec les boucles for..of: les fonctions de générateur.

Il existe déjà de nombreux documents excellents qui expliquent pourquoi et comment utiliser les générateurs. Pour résumer, les générateurs sont des fonctions spéciales qui créent des itérateurs, tandis que les itérateurs sont des objets dotés d'une méthode next(), qui peut être appelée pour obtenir une valeur. Dans une fonction de générateur, le mot clé yield fournit la valeur de next(). L'utilisation de yield suspend l'exécution de la fonction de générateur, ce qui préserve l'état jusqu'à ce que next() soit appelé à nouveau. Le code redémarre alors et continue yield jusqu'à l'arrêt d'une autre fonction. Il existe plusieurs cas d'utilisation canoniques, comme l'utilisation de fonctions d'itération sur les nombres de la séquence de Fibonacci.

Une fois les principes de base terminés, nous allons étudier plus en détail un exemple de code JavaScript qui couvre certains des pièges liés à l'utilisation des générateurs. La page comporte de nombreux commentaires, et vous pouvez tester la version en ligne du code avant de le lire:

Quels sont les principaux points à retenir du code ?

Tout d'abord, la construction d'un générateur génère un itérateur unique avec son propre état. Vous pouvez transmettre des paramètres au constructeur de générateur qui peut contrôler le comportement.

Ensuite, vous pouvez transmettre un paramètre lorsque vous appelez la méthode next() d'un itérateur. Cette valeur sera attribuée à tout ce qui se trouve à gauche de l'instruction yield lors de l'appel précédent de l'itérateur. C'est un excellent moyen de faire varier la sortie de l'itérateur. Ici, nous l'utilisons pour contrôler si le mot généré est en majuscules ou non. Si vous souhaitez influencer la toute première valeur générée, faites-le via un paramètre du constructeur du générateur.

Enfin, les générateurs peuvent produire des itérateurs finis ou infinis. Si vous travaillez avec un itérateur infini, assurez-vous d'avoir une condition de terminal basée sur la valeur yielded. Il est très facile d'écrire accidentellement des boucles infinies, en particulier lorsque vous utilisez for..of à des fins d'itération. Si vous travaillez avec un itérateur fini via des appels à next(), la propriété .done de l'objet renvoyé indique si l'itération est terminée.

Nous espérons que cet exemple, ainsi que les autres ressources disponibles sur le Web, vous intéresseront et vous inciteront à réfléchir à la façon d'utiliser des générateurs dans votre propre code. Les versions de Firefox (à partir de la 31) et de Chrome (à partir de 39) prennent en charge en natif les générateurs. Le projet de régénérateur offre une prise en charge de générateur pour d'autres navigateurs, et l'utilisation de Traceur est également une option.

Merci à Erik Arvidsson d'avoir consulté cet article.