Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
function*
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
Diefunction*-Deklaration erstellt eineBindung einer neuen Generatorfunktion an einen gegebenen Namen. Eine Generatorfunktion kann beendet und später wieder betreten werden, wobei ihr Kontext (variableBindungen) über die Wiedereintrittspunkte hinweg gespeichert wird.
Sie können Generatorfunktionen auch mit demfunction* Ausdruck definieren.
In diesem Artikel
Probieren Sie es aus
function* generator(i) { yield i; yield i + 10;}const gen = generator(10);console.log(gen.next().value);// Expected output: 10console.log(gen.next().value);// Expected output: 20Syntax
function* name(param0) { statements}function* name(param0, param1) { statements}function* name(param0, param1, /* …, */ paramN) { statements}Hinweis:Generatorfunktionen haben keine Pfeilfunktions-Gegenstücke.
Hinweis:function und* sind separate Token, daher können sie durchLeerzeichen oder Zeilenumbrüche getrennt werden.
Parameter
nameDer Funktionsname.
paramOptionalDer Name eines formalen Parameters der Funktion. Für die Syntax der Parameter siehe dieFunktionen Referenz.
statementsOptionalDie Anweisungen, die den Körper der Funktion bilden.
Beschreibung
Einefunction*-Deklaration erstellt einGeneratorFunction-Objekt. Jedes Mal, wenn eine Generatorfunktion aufgerufen wird, gibt sie ein neuesGenerator-Objekt zurück, das demIterator-Protokoll entspricht. Die Ausführung der Generatorfunktion wird bei einem bestimmten Punktsuspendiert, der anfangs am Beginn des Funktionskörpers liegt. Die Generatorfunktion kann mehrfach aufgerufen werden, um mehrere Generatoren gleichzeitig zu erzeugen; jeder Generator behält seinen eigenenAusführungskontext der Generatorfunktion und kann unabhängig betreten werden.
Der Generator erlaubt eine bidirektionale Steuerung des Programmflusses: Der Steuerfluss kann beliebig oft zwischen der Generatorfunktion (Callee) und ihrem Aufrufer übertragen werden, solange beide Parteien dies wünschen. Der Steuerfluss kann vom Aufrufer zum Callee über die Methoden des Generators übertragen werden:next(),throw() undreturn(). Der Steuerfluss kann vom Callee zum Aufrufer übertragen werden, indem die Funktion normal beendet wird, entweder durchreturn,throw, durch Abarbeitung aller Anweisungen, oder durch Nutzung der Ausdrückeyield undyield*.
Wenn die Methodenext() des Generators aufgerufen wird, wird der Körper der Generatorfunktion ausgeführt bis zu einem der folgenden Fälle:
- Ein
yield-Ausdruck. In diesem Fall gibt dienext()-Methode ein Objekt mit einervalue-Eigenschaft, die den ausgegebenen Wert enthält, und einerdone-Eigenschaft, die immerfalseist, zurück. Beim nächsten Aufruf vonnext()ergibt deryield-Ausdruck den Wert, der annext()übergeben wurde. - Ein
yield*, der die Kontrolle an einen anderen Iterator delegiert. In diesem Fall ist dieser Aufruf sowie alle zukünftigennext()-Aufrufe auf den Generator identisch mit Aufrufen vonnext()auf den delegierten Iterator, bis der delegierte Iterator fertig ist. - Eine
return-Anweisung (die nicht von einemtry...catch...finallyabgefangen wird), oder das Ende des Steuerflusses, was implizitreturn undefinedbedeutet. In diesem Fall ist der Generator abgeschlossen, und dienext()-Methode gibt ein Objekt mit einervalue-Eigenschaft, die den zurückgegebenen Wert enthält, und einerdone-Eigenschaft, die immertrueist, zurück. Weiterenext()-Aufrufe haben keinen Effekt und geben stets{ value: undefined, done: true }zurück. - Ein Fehler, der innerhalb der Funktion geworfen wird, entweder durch eine
throw-Anweisung oder eine unbehandelte Ausnahme. Dienext()-Methode wirft diesen Fehler und der Generator ist abgeschlossen. Weiterenext()-Aufrufe haben keinen Effekt und geben immer{ value: undefined, done: true }zurück.
Wenn die Methodethrow() des Generators aufgerufen wird, wirkt es so, als ob einethrow-Anweisung an der aktuellen suspendierten Position in den Körper des Generators eingefügt wird. Similarly, when the generator'sreturn() method is called, it acts as if areturn statement is inserted in the generator's body at the current suspended position. Beide Methoden beenden in der Regel den Generator, es sei denn, die Generatorfunktion fängt den Abschluss übertry...catch...finally ab.
Generatoren wurden früher als Paradigma für asynchrone Programmierung verwendet, umCallback Hell zu vermeiden, indemInversion of Control erreicht wurde. Heute wird dieser Anwendungsfall durch das einfachereasync functions-Modell und dasPromise-Objekt gelöst. Dennoch sind Generatoren weiterhin für viele andere Aufgaben nützlich, wie etwa das Definieren vonIteratoren auf eine unkomplizierte Weise.
function*-Deklarationen verhalten sich ähnlich wiefunction-Deklarationen — sie werdengehoistet an den Anfang ihres Geltungsbereichs und können überall in ihrem Geltungsbereich aufgerufen werden, und sie können nur in bestimmten Kontexten neu deklariert werden.
Beispiele
>Einfaches Beispiel
function* idMaker() { let index = 0; while (true) { yield index++; }}const gen = idMaker();console.log(gen.next().value); // 0console.log(gen.next().value); // 1console.log(gen.next().value); // 2console.log(gen.next().value); // 3// …Beispiel mit yield*
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); // 10console.log(gen.next().value); // 11console.log(gen.next().value); // 12console.log(gen.next().value); // 13console.log(gen.next().value); // 20Übergabe von Argumenten an Generatoren
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 statementgen.next(); // 0gen.next("pretzel"); // 1 pretzelgen.next("california"); // 2 californiagen.next("mayonnaise"); // 3 mayonnaiseRückgabeanweisung in einem Generator
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 Objekt-Eigenschaft
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 Objekt-Methode
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
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 sind nicht konstruierbar
function* f() {}const obj = new f(); // throws "TypeError: f is not a constructorGeneratorbeispiel
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
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-generator-function-definitions> |
Browser-Kompatibilität
Siehe auch
- Leitfaden zu Funktionen
- Leitfaden zu Iteratoren und Generatoren
- Funktionen
GeneratorFunctionfunction*Ausdruckfunctionasync functionasync function*- Iterationsprotokolle
yieldyield*Generator- Regenerator auf GitHub
- Promises and Generators: control flow utopia Vortrag von Forbes Lindesay bei JSConf (2013)
- Task.js auf GitHub
- You Don't Know JS: Async & Performance, Ch.4: Generators von Kyle Simpson