MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-survey

Non-standard. Ne pas utiliser !
La syntaxe de  compréhensions de générateurs ne sont pas une fonctionnalité standard et ont été retirées à partir de Firefox 58. Mieux vaut utiliser les générateurs pour des fonctionnalités similaires.

La syntaxe de compréhension de générateur était une expression qui permettait de construire rapidement une fonction génératrice à partir d'un objet itérable. Toutefois, cette syntaxe a été retirée du standard et de l'implémentation qui en est faite par Firefox. Elle ne doit pas être utilisée.

Syntaxe

(for (x of itérable) x)
(for (x of itérable) if (condition) x)
(for (x of itérable) for (y of itérable) x + y)

Description

Une compréhension de générateur peut contenir deux sortes de composants :

L'itération for-of est toujours le premier composant. Il est possible d'utiliser plusieurs itérations for-of et plusieurs instructions if.

Les compréhensions de tableaux ont un inconvénient majeur : quand on les utilise, un nouveau tableau est créé en mémoire. Cela ne pose pas de problème particulier quand le tableau en question est petit (l'impact sera alors léger) mais lorsque le tableau est très grand (voire infini avec un générateur), cela peut poser problème que de vouloir créer un nouveau tableau.

Les générateurs permettent de calculer des suites à la demande (chaque élément successif est calculé lorsqu'on en a besoin). Les compréhensions de générateurs sont presque identiques, d'une point de vue syntaxique, aux compréhensions de tableaux. Plutôt d'utiliser des crochets, elles utilisent des parenthèses et au lieu de créer un tableau, elles créent un générateur qui pourra être utilisé. Cette notation peut être vue comme une notation raccourcie pour créer des générateurs.

Imaginons qu'on ait un itérateur qui parcourt une grande série d'entiers et qu'on veuille créer un itérateur qui itère sur les doubles de ces entiers. Une compréhension de tableau entraînerait la création d'un tableau complet en mémoire, dont les éléments seraient les valeurs doublées :

var doubles = [for (i in it) i * 2];

En revanche, une compréhension de générateur permettrait de créer un nouvel itérateur qui pourrait être utilisé pour créer les valeurs doublées à la demande, quand on a besoin de les utiliser :

var it2 = (for (i in it) i * 2);
console.log(it2.next()); // La première valeur, doublée
console.log(it2.next()); // La deuxième valeur, doublée

Lorsqu'une compréhension de générateur est utilisée comme un argument d'une fonction, les parenthèses utilisées pour l'appel de la fonction permettent de ne pas écrire les parenthèse encadrant la compréhension :

var résultat = faireQuelqueChose(for (i in it) i * 2);

Avec la compréhension de générateur, on ne parcourt qu'une fois la structure de l'objet alors qu'avec une compréhension de tableau, on parcourt une fois le tableau pour construire la nouvelle version puis une seconde fois quand on souhaite l'utiliser.

Exemples

Compréhensions simples

(for (i of [ 1, 2, 3 ]) i*i );
// fonction génératrice qui générera 1, 4, et 9

[...(for (i of [ 1, 2, 3 ]) i*i )];
// [1, 4, 9]

var abc = [ "A", "B", "C" ];
(for (lettres of abc) lettres.toLowerCase());
// fonction génératrice qui générera "a", "b", et "c"

Compréhensions utilisant une instruction if

var années = [ 1954, 1974, 1990, 2006, 2010, 2014 ];

(for (année of années) if (année > 2000) année);
// fonction génératrice qui générera 2006, 2010, et 2014

(for (année of années) if (année > 2000) if(année < 2010) année);
// fonction génératrice qui générera 2006, équivaut à :

(for (année of années) if (année > 2000 && année < 2010) année);
// fonction génératrice qui générera 2006

Compréhensions de générateurs et fonctions génératrices

Pour mieux comprendre la syntaxe des compréhensions, on peut la comparer avec celle des fonctions génératrices :

Exemple 1 : Générateur simple.

var nombres = [ 1, 2, 3 ];

// Fonction génératrice
(function*() {
  for (let i of nombres) {
    yield i * i;
  }
})()

// Compréhension de générateur
(for (i of nombres) i*i );

// Résultat : les deux instructions renvoient chacune un générateur pour créer [ 1, 4, 9 ]

Second exemple : Un générateur avec if.

var nombres = [ 1, 2, 3 ];

// Fonction génératrice
(function*() {
  for (let i of nombres) {
    if (i < 3) {
      yield i * 1;
    }
  }
})()

// Compréhension
(for (i of nombres) if (i < 3) i);

// Résultat : les deux renvoient un générateur qui générera [ 1, 2 ]

Spécifications

Était initialement prévu pour le brouillon ECMAScript 2015 mais fut retiré lors de la révision 27 (août 2014). Consulter les révisions antérieures d'ES2015 pour les spécifications de cette sémantique.

Compatibilité des navigateurs

FonctionnalitéChromeEdgeFirefoxInternet ExplorerOperaSafari
Support simple Non Non30 Non Non Non
FonctionnalitéAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
Support simple Non Non Non30 Non Non Non

Notes relatives à l'implémentation de SpiderMonkey

  • let n'est pas supporté comme identifiant car il n'est disponible qu'avec JavaScript 1.7 et pour la manipulations des balises de script XUL.
  • La décomposition, utilisée dans les compréhensions, n'est pas encore supportée (bug 980828).

Différences avec les anciennes compréhensions JS 1.7 et JS 1.8

Les compréhensions « JS1.7 / JS1.8 » ont été retirées à partir de Gecko 46 (bug 1220564).

Ancienne syntaxe pour les compréhensions (ne plus l'utiliser) :

[X for (Y in Z)]
[X for each (Y in Z)]
[X for (Y of Z)]

Les différences :

  • Les compréhensions ES2016 créent une portée par nœud for et non pas une portée pour l'ensemble de la compréhension.
    • Ancienne version : [...(()=>x for (x of [0, 1, 2]))][1]() // 2
    • Nouvelle version: [...(for (x of [0, 1, 2]) ()=>x)][1]() // 1, chaque itération crée une nouvelle liaison pour x.
  • Les compréhensions ES2016 débutent par for et non pas l'expression d'affectation.
    • Ancienne version : (i * 2 for (i of nombres))
    • Nouvelle version : (for (i of nombres) i * 2)
  • Les compréhensions ES2016 peuvent utiliser plusieurs composants if et for.
  • Les compréhensions ES2016 ne fonctionnent qu'avec les boucles for...of, pas avec les boucles for...in.

Voir aussi

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : SphinxKnight
 Dernière mise à jour par : SphinxKnight,