for...of

L'instruction for...of permet de créer une boucle Array qui parcourt un objet itérable (ce qui inclut les objets Array, Map, Set, String, TypedArray, l'objet arguments, etc.) et qui permet d'exécuter une instruction pour la valeur de chaque propriété.

Syntaxe

for (variable of iterable)
  instruction
variable
À chaque itération, la valeur d'une propriété différente est affectée à variable.
objet
L'objet dont on parcourt les propriétés énumérables.
instruction
Une instruction à exécuter pour chaque propriété, cette instruction peut être composée de plusieurs instructions en utilisant un bloc d'instructions.

Exemples

Les différences entre for...of et for...in

L'exemple qui suit illustre la différence entre une boucle for...of et une boucle for...in. for...in itère sur les noms des propriétés alors que for...of itère sur les valeurs des propriétés.

Sous un angle plus technique, for...in itèrera sur toutes les propriétés d'un objet dont l'attribut interne [[Enumerable]] vaut true. En revanche, for...of est spécifique aux collections et non aux objets, cette instruction utilisera la propriété [Symbol.iterator].

Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
let arr = [3, 5, 7];
arr.toto = "coucou";

for (let i in arr) {
  console.log(i); // affiche "0", "1", "2", "toto", "arrCustom", "objCustom"
}

for (let i of arr) {
  console.log(i); // affiche "3", "5", "7"
}

Utiliser for...of sur un tableau

let tableauItérable = [1, 2, 3];

for (let valeur of tableauItérable) {
  console.log(valeur);
}
// 1
// 2
// 3

Si la variable n'est pas réaffectée dans la boucle, on pourra également utiliser const à la place de let :

let tableauItérable = [1, 2, 3];

for (const valeur of tableauItérable) {
  console.log(valeur);
}
// 1
// 2
// 3

Utiliser Array.prototype.forEach()

Pour obtenir les mêmes valeurs qu'avec une boucle for...of, on peut utiliser la méthode Array.prototype.forEach() :

let arr = [3, 5, 7];
arr.toto = "coucou";

arr.forEach(function (element, index) {
  console.log(element); // affiche "3", "5", "7"
  console.log(index);  // affiche "0", "1", "2"
});

// ou avec Object.keys()

Object.keys(arr).forEach(function (element, index) {
  console.log(arr[element]); // affiche "3", "5", "7", "coucou"
  console.log(arr[index]);  // affiche "3", "5", "7", undefined
});

Parcourir l'objet arguments

(function() {
  for (let argument of arguments){
    console.log(argument);
  }
})(1, 2, 3);

// 1
// 2
// 3

Parcourir des collections DOM

Il est possible de parcourir des collections DOM telles que NodeList. Dans cet exemple, on ajoute une classe read aux paragraphes qui sont des descendants directs d'un article :

// Note : Cela ne fonctionnera que pour les plates-formes
// qui implémentent NodeList.prototype[Symbol.iterator]
let articleParagraphs = document.querySelectorAll("article > p");

for (let paragraph of articleParagraphs) {
  paragraph.classList.add("read");
}

Clôturer les itérateurs

Dans les boucles for...of, on peut provoquer la fin de l'itérateur avec break, continue, throw, ou return. Dans ces cas, l'itérateur est fermé.

function* toto() {
  yield 1;
  yield 2;
  yield 3;
};

for (let o of toto()) {
  console.log(o);
  break; // L'itérateur est fermé
}

Itérer sur les générateurs

Grâce à cette instruction, on peut également itérer sur les générateurs :

function* fibonacci() { // une fonction génératrice
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // on arrête la séquence à 1000
  if (n >= 1000){
    break;
  }
}

Itérer sur les autres objets itérables

Il est aussi possible d'itérer sur un objet qui implémente le protocole itérable de façon explicite :

var iterable = {
  [Symbol.iterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return { value: this.i++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (var value of iterable) {
  console.log(value);
}
// 0
// 1
// 2

Attention à ne pas réutiliser les générateurs

Les générateurs ne doivent pas être réutilisés, même lorsque la boucle for...of a été interrompue (par exemple lorsque break est utilisé). Lorsqu'on quitte une boucle, le générateur est clôturé et si on l'utilise à nouveau, il ne fournira aucun résultat. Firefox n'a pas encore implémenté ce comportement standard (cf. bug 1147371).

var gen = (function *(){
  yield 1;
  yield 2;
  yield 3;
})();
for (let o of gen) {
  console.log(o);
  break; // L'itérateur est fermé
}

// Le générateur ne doit pas être réutilisé !
for (let o of gen){
  console.log(o); // Ceci n'est jamais exécuté
}

Spécifications

Spécification État Commentaires
ECMAScript 2015 (6th Edition, ECMA-262)
La définition de 'instruction for...of' dans cette spécification.
Standard Définition initiale.
ECMAScript 2017 Draft (ECMA-262)
La définition de 'instruction for...of' dans cette spécification.
Projet  

Compatibilité des navigateurs

Fonctionnalité Chrome Firefox (Gecko) Edge Opera Safari
Support simple 38 [1]
51 [3]
13 (13) [2] 12 25 7.1
Clôture des itérateurs (Oui) 53 (53) (Oui) (Oui) (Oui)
Fonctionnalité Android Chrome pour Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Support simple 5.1 38 [1]
51 [3]
13.0 (13) [2] Pas de support ? 8
Clôture des itérateurs (Oui) (Oui) 53.0 (53) (Oui) (Oui) (Oui)

[1] Pour les versions de Chrome entre Chrome 29 et Chrome 37, cette fonctionnalité était disponible grâce à une préférence utilisateur. Sous chrome://flags/#enable-javascript-harmony, activer le paramètre « Activer la fonctionnalité expérimentale JavaScript ».

[2] Avant Firefox 51, lorsqu'on utilisait une boucle for...of avec le mot-clé const, cela générait une exception SyntaxError ("missing = in const declaration"). Cela a été corrigé (bug 1101653).

[3] Le mécanisme d'itération est ajouté sur les objets semblables à des tableaux à partir de Chrome 51.

Voir aussi

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : SphinxKnight, Swarmpan, jfrag, marie-ototoi, fscholz, senshu
 Dernière mise à jour par : SphinxKnight,