Parcourir un tableau a longtemps demandé un compteur, une condition et une incrémentation, soit trois occasions de se tromper. La boucle for...of a supprimé cette cérémonie : elle donne directement les valeurs, une par une.
Le mot of ne s'utilise pratiquement que dans cette construction. Il sépare la variable qui reçoit chaque valeur de la collection qu'on parcourt.
Définition
of est le mot-clé de la boucle for...of, qui parcourt les valeurs d'une collection parcourable et exécute son bloc une fois par valeur.
const articles = ['thé', 'café', 'sucre'];
for (const article of articles) {
console.log(article);
}
// 'thé', puis 'café', puis 'sucre'La variable se déclare avec const presque toujours : elle est recréée à chaque tour, et rien n'a besoin de la modifier dans le bloc.
for...of ou for...in
Les deux boucles se ressemblent et ne font pas du tout la même chose. C'est la confusion la plus fréquente sur le sujet.
| Boucle | Ce qu'elle donne | Sur un tableau |
|---|---|---|
for...of | Les valeurs | 'thé', 'café' |
for...in | Les noms de propriétés | '0', '1', en texte |
Sur un tableau, for...in renvoie des indices sous forme de texte, et remonte aussi les propriétés héritées. La règle : of pour les valeurs d'une collection, in pour les clés d'un objet.
Ce qui se parcourt, et ce qui ne se parcourt pas
La boucle accepte tout ce que le langage considère comme parcourable : un Array (tableau), une chaîne de caractères, un Map, un Set, les résultats d'une sélection dans une page.
for (const lettre of 'thé') { } // 't', 'h', 'é'
for (const valeur of new Set([1, 1, 2])) { } // 1, 2
for (const [cle, valeur] of new Map()) { } // pairesUn objet ordinaire, lui, n'est pas parcourable : la boucle lève une erreur. Le passage obligé est Object.entries(), associé à une Destructuration pour récupérer la clé et la valeur.
const stock = { the: 12, cafe: 3 };
for (const [produit, quantite] of Object.entries(stock)) {
console.log(produit, quantite);
}Ce que forEach ne sait pas faire
La méthode Array.forEach() est plus courte, mais elle ne s'interrompt pas. Un break ou un continue n'y a aucun effet, et un await à l'intérieur n'est pas attendu.
for (const id of identifiants) {
const fiche = await charge(id);
if (!fiche) break;
}C'est le critère de choix le plus fiable : dès qu'il faut s'arrêter en cours de route ou attendre quelque chose à chaque tour, for...of s'impose. Pour une transformation simple, Map ou Array.filter() restent plus expressifs.
Questions fréquentes
Comment obtenir l'indice en même temps que la valeur ?
La méthode entries() d'un tableau renvoie des paires, qui se déballent directement dans la boucle : for (const [i, valeur] of articles.entries()). C'est plus lisible que de gérer un compteur à part, et l'indice reste toujours synchronisé avec la valeur.
Pourquoi mon objet provoque-t-il une erreur ?
Parce qu'un objet ordinaire ne sait pas se parcourir : le message indique qu'il n'est pas parcourable. Passez par Object.keys(), Object.values() ou Object.entries() selon ce dont vous avez besoin, ces trois méthodes renvoyant des tableaux.
Le mot of existe-t-il ailleurs dans le langage ?
On le retrouve dans for await...of, pour parcourir des valeurs qui arrivent au fil du temps, et dans la méthode Array.of(), qui construit un tableau à partir des valeurs reçues. À noter que Array.of(7) donne un tableau d'un élément, là où Array(7) en crée un de sept cases vides.