W3docs

Itérables et itérateurs JavaScript

Comprendre les itérables est fondamental en JavaScript. Ils permettent un accès séquentiel aux éléments et s'intègrent aux boucles, spread et destructuration.

Introduction aux itérables JavaScript

Les itérables JavaScript sont des objets qui implémentent un protocole spécifique, leur permettant d'être consommés par des constructions d'itération telles que for...of. Ce guide couvre les concepts fondamentaux, les itérables intégrés et les techniques pratiques pour travailler avec des collections.

Que sont les itérables en JavaScript ?

Dans sa forme la plus simple, un itérable est un object qui implémente la méthode Symbol.iterator, permettant un accès séquentiel à ses éléments. Plusieurs types intégrés en JavaScript sont itérables, notamment Array, String, Map, Set et bien d'autres. Il est important de distinguer un itérable (l'object parcouru) d'un itérateur (l'object renvoyé par Symbol.iterator qui effectue réellement le parcours). Ces itérables sont essentiels à diverses opérations, comme la boucle et la manipulation de données.

Info

Pour une exploration détaillée des objets JavaScript Map et Set, veuillez consulter notre guide complet sur JavaScript Map et Set.

Exemple d'itérable : Array

Voyons un exemple basique d'itérable en JavaScript :

javascript— editable

Cet extrait de code illustre l'itération sur un array de fruits, un itérable courant. La boucle for...of appelle automatiquement la méthode Symbol.iterator de l'itérable et consomme l'itérateur résultant jusqu'à ce que done soit true. Voir les boucles JavaScript pour la famille complète des constructions de boucle.

Avertissement

Ne confondez pas for...of avec for...in. for...of itère sur les valeurs produites par un itérable (éléments d'array, caractères de string, entrées de Map). for...in itère sur les clés de propriété énumérables d'un object — y compris les héritées — et est destiné aux objets simples, pas aux arrays. Utiliser for...in sur un array donne des strings d'index ("0", "1", …) et peut récupérer des propriétés supplémentaires, donc préférez for...of pour les données ordonnées.

Le protocole itérateur

La pierre angulaire d'un itérable est sa méthode Symbol.iterator. Le protocole est un contrat précis :

  1. Un itérable possède une méthode identifiée par Symbol.iterator. L'appeler renvoie un itérateur.
  2. Un itérateur est un object avec une méthode next().
  3. Chaque appel à next() renvoie un object { value, done } :
    • done: falsevalue est l'élément suivant dans la séquence.
    • done: true — l'itération est terminée (value est alors ignorée, ou porte un résultat final optionnel).

Tout object qui respecte ce contrat fonctionne avec for...of, l'opérateur spread, la déstructuration et Array.from() — même si vous avez écrit l'object vous-même. Symbol est une clé unique intégrée ; voir le type Symbol pour comprendre pourquoi ces méthodes de protocole en utilisent une plutôt qu'un nom de string ordinaire.

Exemple : un itérable range personnalisé

Un cas d'usage classique est un object qui produit une plage numérique de manière paresseuse, sans jamais construire un array :

javascript— editable

Dans cet exemple, la méthode [Symbol.iterator]() renvoie un nouvel itérateur à chaque fois, de sorte que le même object range peut être parcouru plusieurs fois. La syntaxe abrégée de méthode garantit que this fait bien référence à l'object range. (Utiliser une fonction fléchée pour [Symbol.iterator] capturerait this de manière lexicale et casserait le schéma.)

Les générateurs : la façon simple de créer des itérables

Écrire next() et gérer l'état manuellement est verbeux. Une fonction génératrice — déclarée avec function* et utilisant yield — produit automatiquement un itérateur. Chaque yield met la fonction en pause et transmet une valeur au consommateur ; l'exécution reprend au prochain appel à next(). Le même range devient beaucoup plus concis :

javascript— editable

Le * avant le nom de la méthode en fait une méthode génératrice, donc range est itérable avec presque aucun code répétitif. Pour tout ce que les générateurs peuvent faire — y compris la communication bidirectionnelle et la délégation avec yield* — voir les générateurs et les itérateurs et générateurs asynchrones.

Séquences infinies et paresseuses

Étant donné qu'un itérateur ne calcule la valeur suivante qu'à la demande, il peut décrire des séquences trop grandes — ou même infinies — pour tenir en mémoire. C'est la principale raison d'écrire un itérateur personnalisé plutôt que d'utiliser simplement un array :

javascript— editable
Avertissement

N'utilisez jamais le spread ([...naturals()]) ni for...of sans break sur un itérable infini — il bouclera indéfiniment. Récupérez un nombre fini de valeurs avec next() à la place.

Consommer des itérables

Une fois qu'un object est itérable, tout le langage lui est ouvert : toute construction qui accepte un itérable fonctionne avec votre type personnalisé de la même façon qu'avec les arrays.

Utiliser Array.from()

La méthode Array.from() crée un nouvel array à partir de n'importe quel itérable (ou object de type array). Elle accepte également une fonction de mappage optionnelle comme second argument, appliquée à chaque élément lors de la construction de l'array — plus pratique que Array.from(it).map(fn) car cela évite une seconde passe :

javascript— editable

Voir JavaScript Map et Set pour en savoir plus sur Set, et les méthodes d'array pour ce que vous pouvez faire une fois que vous avez un array.

La syntaxe spread avec les itérables

La syntaxe spread (...) développe un itérable partout où des arguments ou des éléments sont attendus — pour fusionner des arrays, les copier ou passer des éléments comme arguments de fonction :

javascript— editable

Pour une vue d'ensemble complète de ... dans les positions spread et collect, voir les paramètres rest et la syntaxe spread.

Déstructuration et rest

La déstructuration extrait des valeurs de n'importe quel itérable par position, et le schéma rest (...) rassemble ce qui reste dans un array :

javascript— editable

En savoir plus dans la déstructuration.

L'itérable string et la sécurité Unicode

Les strings sont itérables, et l'itérateur parcourt de manière cruciale les points de code Unicode, et non les unités de code 16 bits. Cela signifie que les caractères en paires de substitution (emoji, certains scripts) sont conservés intacts — contrairement à l'indexation avec [i] ou aux anciennes boucles for sur .length, qui peuvent les diviser :

javascript— editable

Chaque fois que vous devez compter ou diviser des caractères visibles par l'utilisateur correctement, itérez la string (ou appliquez-y le spread) plutôt que de vous fier à .length. Voir le chapitre Strings pour en savoir plus.

Récapitulatif

  • Un object est itérable quand il possède une méthode [Symbol.iterator]() qui renvoie un itérateur — un object dont next() produit { value, done }.
  • Préférez un générateur (function* / yield) plutôt que d'écrire next() manuellement ; c'est la façon la plus courte et la moins sujette aux erreurs de rendre quelque chose d'itérable.
  • Utilisez for...of pour les valeurs de données ordonnées/itérables ; utilisez for...in uniquement pour les clés des objets simples.
  • Une fois itérable, votre type s'intègre gratuitement dans spread, déstructuration, rest, Array.from(it, mapFn) et de nombreuses API intégrées.
  • Les itérateurs sont paresseux, ils peuvent donc modéliser des séquences infinies ou très volumineuses qu'un array ne pourrait jamais gérer.
  • Itérez les strings (ne les indexez pas) pour gérer les caractères Unicode comme les emoji en toute sécurité.

Pratique

Pratique
Lesquelles des affirmations suivantes sur les itérables JavaScript sont correctes ?
Lesquelles des affirmations suivantes sur les itérables JavaScript sont correctes ?
Was this page helpful?