Itérateurs (Symbol.iterator)

Le protocole d’itération : un objet avec une méthode [Symbol.iterator]() fonctionne avec for...of, le spread et la déstructuration.

Sur cette page

Exemple

#
JavaScript
const tasks = ['Quiz', 'Projet']
const iterator = tasks[Symbol.iterator]()

console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
Console
{ value: 'Quiz', done: false }
{ value: 'Projet', done: false }
{ value: undefined, done: true }

C’est exactement ainsi que fonctionne la boucle for...of : elle récupère l’itérateur et appelle next() jusqu’à obtenir done: true.

Définition et utilisation

#

L’itération en JavaScript repose sur un contrat simple. Un objet itérable a une méthode à la clé Symbol.iterator, qui renvoie un itérateur. Un itérateur est un objet avec une méthode next(), qui renvoie à chaque appel un résultat { value, done } : la valeur suivante et l’information indiquant si c’est déjà la fin.

Ce contrat est utilisé par for...of, le spread [...x], la déstructuration de tableau, Array.from(), les constructeurs Map et Set, ainsi que Promise.all(). Les tableaux, les chaînes, Map, Set et les listes NodeList sont itérables d’emblée. Un objet ordinaire {} ne l’est pas, c’est pourquoi for...of lève une TypeError sur lui.

Vous rendez votre propre objet ou classe itérable en ajoutant une méthode [Symbol.iterator](). Le plus simple est de l’écrire comme un générateur, *[Symbol.iterator]() {}, car les générateurs créent eux-mêmes des itérateurs corrects. Les navigateurs sortis depuis 2025 ont aussi des méthodes utilitaires d’itérateurs, comme map(), filter(), take() et toArray(), qui traitent les valeurs de façon paresseuse, sans créer de tableaux intermédiaires.

Syntaxe

#
Syntaxe
const iterator = iterable[Symbol.iterator]()
iterator.next()

class Name {
  *[Symbol.iterator]() {
    yield value
  }
}

Plus d’exemples

#
Une classe itérable personnalisée
JavaScript
class Course {
  constructor(title, lessons) {
    this.title = title
    this.lessons = lessons
  }

  *[Symbol.iterator]() {
    for (const lesson of this.lessons) {
      yield `${this.title}: ${lesson}`
    }
  }
}

const course = new Course('CSS', ['Sélecteurs', 'Flexbox', 'Grid'])

for (const lesson of course) {
  console.log(lesson)
}
console.log([...course].length)
Console
CSS: Sélecteurs
CSS: Flexbox
CSS: Grid
3
Un itérateur écrit à la main
JavaScript
const countdown = {
  from: 3,
  [Symbol.iterator]() {
    let current = this.from
    return {
      next() {
        if (current > 0) {
          return { value: current--, done: false }
        }
        return { value: undefined, done: true }
      }
    }
  }
}

console.log([...countdown])
const [first, second] = countdown
console.log(first, second)
Console
[3, 2, 1]
3 2

Le même objet fonctionne avec le spread et avec la déstructuration, car les deux constructions appellent [Symbol.iterator]() et récupèrent les valeurs via next().

Piège : un objet ordinaire n’est pas itérable
JavaScript
const scores = { Léa: 120, Lucas: 95 }

try {
  for (const score of scores) {
    console.log(score)
  }
} catch (error) {
  console.log(error.name)
}

console.log(typeof scores[Symbol.iterator])
console.log(typeof [][Symbol.iterator])

for (const [name, points] of Object.entries(scores)) {
  console.log(name, points)
}
Console
TypeError
undefined
function
Léa 120
Lucas 95

Compatibilité des navigateurs

#

Largement disponible

Fonctionne dans tous les navigateurs modernes, y compris sur mobile. Vous pouvez l’utiliser sans crainte.

  • Chrome
  • Edge
  • Firefox
  • Safari

Bonnes pratiques

#
  • La méthode [Symbol.iterator]() est la plus simple à écrire comme un générateur avec yield. Vous n’avez alors pas besoin de construire manuellement les objets { value, done }.
  • Un objet itérable, par ex. un tableau, crée un nouvel itérateur à chaque boucle, donc on peut le parcourir plusieurs fois. L’itérateur ou le générateur lui-même, une fois épuisé, ne renverra plus aucune valeur.
  • Pour vérifier si une valeur peut être parcourue avec for...of, utilisez la condition typeof value?.[Symbol.iterator] === "function".

Entrées associées

#

Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.