function*

Déclare un générateur : une fonction qui livre des valeurs successives via yield et se met en pause entre elles.

Renvoie
L’appel d’une fonction génératrice renvoie un objet générateur, qui est à la fois un itérateur et un objet itérable.
Sur cette page

Exemple

#
JavaScript
function* lessonSteps() {
  yield 'Vidéo'
  yield 'Théorie'
  yield 'Quiz'
}

const steps = lessonSteps()

console.log(steps.next())
console.log(steps.next())
console.log(steps.next())
console.log(steps.next())
Console
{ value: 'Vidéo', done: false }
{ value: 'Théorie', done: false }
{ value: 'Quiz', done: false }
{ value: undefined, done: true }

Définition et utilisation

#

Une fonction écrite comme function* est un générateur. Son appel ne lance pas le code immédiatement, il renvoie seulement un objet générateur. Le code ne démarre qu’après l’appel de next(), et s’exécute jusqu’au prochain yield, qui livre une valeur et arrête la fonction à cet endroit. Le next() suivant reprend le travail exactement là où il s’était arrêté.

Chaque next() renvoie un objet { value, done }. Tant que le générateur atteint de nouveaux yield, le champ done vaut false. Quand la fonction termine son exécution ou rencontre un return, vous obtenez done: true. Le générateur est un objet itérable, donc vous pouvez le parcourir avec for...of, le décomposer avec le spread [...gen] ou le passer à Array.from().

Les générateurs calculent les valeurs de façon paresseuse, c’est-à-dire seulement quand elles sont nécessaires. Grâce à cela, ils peuvent décrire même des suites infinies, par ex. des identifiants successifs, sans occuper de mémoire. yield* transmet toutes les valeurs d’un autre objet itérable, et async function* crée un générateur asynchrone, que l’on parcourt avec la boucle for await...of.

Syntaxe

#
Syntaxe
function* name(params) {
  yield value
  yield* iterable
  return finalValue
}

const generator = name()
generator.next()

Plus d’exemples

#
Un générateur dans une boucle for...of et dans le spread
JavaScript
function* range(start, end, step = 1) {
  for (let i = start; i <= end; i += step) {
    yield i
  }
}

for (const level of range(1, 3)) {
  console.log(`Niveau ${level}`)
}

console.log([...range(0, 20, 5)])
Console
Niveau 1
Niveau 2
Niveau 3
[0, 5, 10, 15, 20]
Une suite infinie d’identifiants
JavaScript
function* createIds(prefix) {
  let id = 1
  while (true) {
    yield `${prefix}-${id}`
    id++
  }
}

const taskIds = createIds('task')

console.log(taskIds.next().value)
console.log(taskIds.next().value)
console.log(taskIds.next().value)
Console
task-1
task-2
task-3

La boucle while (true) ne bloque pas le programme, car le générateur s’arrête à chaque yield et attend le prochain appel de next().

Combiner des générateurs avec yield*
JavaScript
function* frontend() {
  yield 'HTML'
  yield 'CSS'
}

function* fullStack() {
  yield* frontend()
  yield 'JavaScript'
  yield* ['Node.js', 'SQL']
}

console.log([...fullStack()])
Console
['HTML', 'CSS', 'JavaScript', 'Node.js', 'SQL']

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

#
  • On ne peut parcourir un générateur qu’une seule fois. Quand vous avez besoin des valeurs à nouveau, appelez encore la fonction génératrice ou enregistrez les résultats dans un tableau.
  • La valeur d’un return a done: true, donc la boucle for...of et le spread l’ignorent. Tout ce qui doit se retrouver dans le résultat doit être livré par yield.
  • Ne décomposez pas un générateur infini avec le spread ni avec Array.from(). Récupérez ses valeurs avec next() ou interrompez la boucle avec break.

Entrées associées

#

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