Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

function*

Baseline
Weitgehend verfügbar

Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit September 2016 browserübergreifend verfügbar.

Die function*-Deklaration erstellt eine Bindung einer neuen Generatorfunktion an einen bestimmten Namen. Eine Generatorfunktion kann verlassen und später wieder aufgenommen werden. Ihr Kontext (die Bindungen ihrer Variablen) bleibt dabei erhalten.

Sie können Generatorfunktionen auch mit einem function*-Ausdruck definieren.

Probieren Sie es aus

function* generator(i) {
  yield i;
  yield i + 10;
}

const gen = generator(10);

console.log(gen.next().value);
// Expected output: 10

console.log(gen.next().value);
// Expected output: 20

Syntax

js
function* name(param0) {
  statements
}
function* name(param0, param1) {
  statements
}
function* name(param0, param1, /* …, */ paramN) {
  statements
}

Hinweis: Für Generatorfunktionen gibt es keine entsprechende Pfeilfunktionssyntax.

Hinweis: function und * sind separate Token und können daher durch Leerzeichen oder Zeilenumbrüche getrennt werden.

Parameter

name

Der Name der Funktion.

param Optional

Der Name eines formalen Parameters der Funktion. Informationen zur Syntax von Parametern finden Sie in der Referenz zu Funktionen.

statements Optional

Die Anweisungen, aus denen der Funktionskörper besteht.

Beschreibung

Eine function*-Deklaration erstellt ein GeneratorFunction-Objekt. Bei jedem Aufruf einer Generatorfunktion gibt sie ein neues Generator-Objekt zurück, das dem Iterator-Protokoll entspricht. Die Ausführung der Generatorfunktion ist an einer Stelle angehalten – anfangs ganz zu Beginn des Funktionskörpers. Die Generatorfunktion kann mehrfach aufgerufen werden, um mehrere Generatoren gleichzeitig zu erstellen. Jeder Generator verwaltet seinen eigenen Ausführungskontext der Generatorfunktion und kann unabhängig von den anderen schrittweise ausgeführt werden.

Der Generator ermöglicht einen Kontrollfluss in beide Richtungen: Der Kontrollfluss kann beliebig oft zwischen der Generatorfunktion (der aufgerufenen Funktion) und der aufrufenden Funktion wechseln. Von der aufrufenden Funktion zur Generatorfunktion wechselt er durch Aufrufe der Generatormethoden next(), throw() und return(). In die Gegenrichtung wechselt er, wenn die Funktion regulär durch return oder throw oder nach der Ausführung aller Anweisungen verlassen wird, oder durch Verwendung der Ausdrücke yield und yield*.

Wenn die Methode next() des Generators aufgerufen wird, wird der Körper der Generatorfunktion bis zu einem der folgenden Punkte ausgeführt:

  • Ein yield-Ausdruck. In diesem Fall gibt die Methode next() ein Objekt zurück, dessen Eigenschaft value den mit yield bereitgestellten Wert enthält und dessen Eigenschaft done immer false ist. Beim nächsten Aufruf von next() wird der yield-Ausdruck zu dem Wert ausgewertet, der an next() übergeben wurde.
  • Ein yield*-Ausdruck, der an einen anderen Iterator delegiert. In diesem Fall entsprechen dieser und alle weiteren Aufrufe von next() auf dem Generator Aufrufen von next() auf dem Iterator, an den delegiert wurde, bis dieser abgeschlossen ist.
  • Eine return-Anweisung (die nicht von try...catch...finally abgefangen wird) oder das Ende des Kontrollflusses, das implizit return undefined bedeutet. In diesem Fall ist der Generator abgeschlossen. Die Methode next() gibt ein Objekt zurück, dessen Eigenschaft value den zurückgegebenen Wert enthält und dessen Eigenschaft done immer true ist. Weitere Aufrufe von next() haben keine Wirkung und geben immer { value: undefined, done: true } zurück.
  • Ein innerhalb der Funktion ausgelöster Fehler, entweder durch eine throw-Anweisung oder durch eine nicht behandelte Ausnahme. Die Methode next() löst diesen Fehler aus, und der Generator ist abgeschlossen. Weitere Aufrufe von next() haben keine Wirkung und geben immer { value: undefined, done: true } zurück.

Wenn die Methode throw() des Generators aufgerufen wird, wirkt dies so, als würde an der aktuellen angehaltenen Position eine throw-Anweisung in den Körper des Generators eingefügt. Entsprechend wirkt ein Aufruf der Methode return() so, als würde dort eine return-Anweisung eingefügt. Beide Methoden schließen den Generator normalerweise ab, sofern die Generatorfunktion den jeweiligen Abschluss nicht mit try...catch...finally abfängt.

Generatoren wurden früher als Paradigma für die asynchrone Programmierung verwendet. Durch Inversion of Control ließ sich damit die sogenannte Callback Hell vermeiden. Heute wird dieser Anwendungsfall mit dem einfacheren Modell der asynchronen Funktionen und dem Promise-Objekt abgedeckt. Generatoren sind jedoch weiterhin für viele andere Aufgaben nützlich, etwa um Iteratoren auf unkomplizierte Weise zu definieren.

function*-Deklarationen verhalten sich ähnlich wie function-Deklarationen: Sie werden an den Anfang ihres Gültigkeitsbereichs gehoben und können überall innerhalb dieses Bereichs aufgerufen werden. Eine erneute Deklaration ist nur in bestimmten Kontexten möglich.

Beispiele

Einfaches Beispiel

js
function* idMaker() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// …

Beispiel mit yield*

js
function* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function* generator(i) {
  yield i;
  yield* anotherGenerator(i);
  yield i + 10;
}

const gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20

Argumente an Generatoren übergeben

js
function* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

const gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise

Return-Anweisung in einem Generator

js
function* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

const gen = yieldAndReturn();
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }

Generator als Objekteigenschaft

js
const someObj = {
  *generator() {
    yield "a";
    yield "b";
  },
};

const gen = someObj.generator();

console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }

Generator als Objektmethode

js
class Foo {
  *generator() {
    yield 1;
    yield 2;
    yield 3;
  }
}

const f = new Foo();
const gen = f.generator();

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

Generator als berechnete Eigenschaft

js
class Foo {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
  }
}

const SomeObj = {
  *[Symbol.iterator]() {
    yield "a";
    yield "b";
  },
};

console.log(Array.from(new Foo())); // [ 1, 2 ]
console.log(Array.from(SomeObj)); // [ 'a', 'b' ]

Generatoren können nicht mit new aufgerufen werden

js
function* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor

Generatorbeispiel

js
function* powers(n) {
  // Endless loop to generate
  for (let current = n; ; current *= n) {
    yield current;
  }
}

for (const power of powers(2)) {
  // Controlling generator
  if (power > 32) {
    break;
  }
  console.log(power);
  // 2
  // 4
  // 8
  // 16
  // 32
}

Spezifikationen

Spezifikation
ECMAScript® 2027 Language Specification
# sec-generator-function-definitions

Browser-Kompatibilität

Siehe auch