Array.forEach() en JavaScript : parcourir un tableau pour agir

forEach appelle une fonction sur chaque élément et ne rend rien : ce qu'il interdit, le piège de l'attente asynchrone et quand préférer for...of.
3 min de lecture
Believemy logo

Parcourir un tableau pour faire quelque chose de chaque élément, écrire une ligne de journal, envoyer un message, mettre à jour l'affichage : voilà le seul emploi de forEach.

Il ne construit rien et ne renvoie rien. C'est à la fois sa simplicité et sa limite.


Définition

forEach est une méthode d'Array (tableau) qui appelle une fonction sur chaque élément, dans l'ordre, et rend undefined. Ce que la fonction renvoie est ignoré.

JAVASCRIPT
const articles = ["clavier", "souris"];

const retour = articles.forEach((a, i) => console.log(i, a));
// 0 clavier
// 1 souris

console.log(retour);   // undefined

Cette valeur de retour interdit tout enchaînement. Écrire articles.forEach(...).filter(...) lève une TypeError, puisque la méthode est alors appelée sur undefined. Une chaîne de traitements passe donc par Array.map() et Array.filter().


Ce qu'il ne sait pas faire

break et continue n'ont aucun sens à l'intérieur : ils appartiennent aux boucles, pas aux fonctions. Un return dans le corps quitte seulement le tour en cours, exactement comme un continue.

JAVASCRIPT
// Sortir en cours de route demande une vraie boucle
for (const n of [1, 2, 3]) {
  if (n === 2) break;
  console.log(n);   // 1
}

Quand l'objectif est justement de s'arrêter tôt, deux méthodes le font d'elles-mêmes : Array.some() interrompt au premier succès, Array.find() rend l'élément trouvé et cesse le parcours.


Le piège de l'attente

Une fonction async rend une Promise, et forEach jette ce que la fonction renvoie. Il ne l'attend donc jamais.

JAVASCRIPT
const attendre = (ms) => new Promise((ok) => setTimeout(ok, ms));

async function envoyer(ids) {
  ids.forEach(async (id) => {
    await attendre(10);
    console.log("envoyé", id);
  });
  console.log("terminé");   // s'affiche AVANT les envois
}

La ligne « terminé » sort la première, et une erreur survenue dans un envoi ne remonte nulle part. Pour attendre réellement, il faut une boucle of avec await, ou Promise.all sur un Array.map() lorsque les envois sont indépendants.


Questions fréquentes

Question

forEach ou for...of ?

La boucle for...of accepte break, continue et await, ce qui en fait le choix par défaut le plus sûr. forEach garde l'avantage de la brièveté sur une action courte, dans une chaîne où l'on veut rester en style fonctionnel.

Question

Parcourt-il les cases vides d'un tableau ?

Non, il les saute. Sur [1, , 3], la fonction est appelée aux positions 0 et 2 seulement, et la case du milieu est ignorée sans avertissement. Ces tableaux à trous sont rares mais apparaissent après un delete ou une affectation au-delà de la fin.

Question

Peut-on modifier le tableau pendant le parcours ?

Techniquement oui, mais le nombre de tours est fixé au départ : les éléments ajoutés en route ne sont jamais visités, et une suppression décale les suivants, qui se retrouvent alors sautés. Construisez plutôt un nouveau tableau.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.