Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
yield*
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.
Deryield*-Operator kann innerhalb von Generatorfunktionen (synchron oder asynchron) verwendet werden, um an ein anderesiterierbares Objekt, wie zum Beispiel einenGenerator, zu delegieren. Innerhalb asynchroner Generatorfunktionen kann er zusätzlich verwendet werden, um an ein weiteres asynchrones iterierbares Objekt, wie einenAsyncGenerator, zu delegieren.
In diesem Artikel
Probieren Sie es aus
function* func1() { yield 42;}function* func2() { yield* func1();}const iterator = func2();console.log(iterator.next().value);// Expected output: 42Syntax
yield* expressionParameter
expressionOptionalEin iterierbares Objekt.
Rückgabewert
Gibt den Wert zurück, der von diesem Iterator zurückgegeben wird, wenn er geschlossen wird (wenndonetrue ist).
Beschreibung
Deryield*-Ausdruck iteriert über den Operanden und yieldet jeden von ihm zurückgegebenen Wert. Er delegiert die Iteration des aktuellen Generators an einen zugrunde liegenden Iterator — die wir im Folgenden als "Generator" und "Iterator" bezeichnen werden.yield* holt zunächst den Iterator vom Operanden, indem die[Symbol.iterator]()-Methode des letzteren aufgerufen wird. Dann, jedes Mal, wenn dienext()-Methode des Generators aufgerufen wird, ruftyield* dienext()-Methode des Iterators auf, übergibt das vom Generator mitnext() empfangene Argument (immerundefined beim ersten Aufruf), und yieldet dasselbe Ergebnisobjekt wie das, was von dernext()-Methode des Iterators zurückgegeben wird. Wenn das Iterator-Ergebnisdone: true hat, dann hört deryield*-Ausdruck auf zu laufen und gibt denvalue dieses Ergebnisses zurück.
Deryield*-Operator leitet auch diethrow()- undreturn()-Methoden des aktuellen Generators an den zugrunde liegenden Iterator weiter. Wenn der aktuelle Generator vorzeitig durch eine dieser Methoden geschlossen wird, wird der zugrunde liegende Iterator informiert. Wenn diethrow()/return()-Methode des Generators aufgerufen wird, wird diethrow()/return()-Methode des zugrunde liegenden Iterators mit demselben Argument aufgerufen. Der Rückgabewert vonthrow()/return() wird ähnlich wie das Ergebnis dernext()-Methode behandelt, und wenn die Methode wirft, wird die Ausnahme vomyield*-Ausdruck weitergegeben.
Falls der zugrunde liegende Iterator keinereturn()-Methode besitzt, wird deryield*-Ausdruck in einereturn-Anweisung umgewandelt, ebenso als würdereturn() auf einem angehaltenenyield-Ausdruck aufgerufen.
Falls der zugrunde liegende Iterator keinethrow()-Methode besitzt, führt dies dazu, dassyield* einenTypeError wirft – doch bevor der Fehler geworfen wird, wird diereturn()-Methode des zugrunde liegenden Iterators aufgerufen, falls eine existiert.
Beispiele
>Delegieren an einen anderen Generator
Im folgenden Code werden Werte, die vong1() yielded werden, vonnext()-Aufrufen genauso zurückgegeben wie diejenigen, die vong2() yielded werden.
function* g1() { yield 2; yield 3; yield 4;}function* g2() { yield 1; yield* g1(); yield 5;}const gen = g2();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: 4, done: false}console.log(gen.next()); // {value: 5, done: false}console.log(gen.next()); // {value: undefined, done: true}Andere iterierbare Objekte
Neben Generator-Objekten kannyield* auch andere Arten von Iterables yielden (z. B. Arrays, Strings oderarguments-Objekte).
function* g3(...args) { yield* [1, 2]; yield* "34"; yield* args;}const gen = g3(5, 6);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: "4", done: false}console.log(gen.next()); // {value: 5, done: false}console.log(gen.next()); // {value: 6, done: false}console.log(gen.next()); // {value: undefined, done: true}Der Wert des yield* Ausdrucks selbst
yield* ist ein Ausdruck, keine Anweisung, daher wird er zu einem Wert ausgewertet.
function* g4() { yield* [1, 2, 3]; return "foo";}function* g5() { const g4ReturnValue = yield* g4(); console.log(g4ReturnValue); // 'foo' return g4ReturnValue;}const gen = g5();console.log(gen.next()); // {value: 1, done: false}console.log(gen.next()); // {value: 2, done: false}console.log(gen.next()); // {value: 3, done: false} done is false because g5 generator isn't finished, only g4console.log(gen.next()); // {value: 'foo', done: true}Verwendung mit asynchronen Generatoren
async function* g1() { await Promise.resolve(0); yield "foo";}function* g2() { yield "bar";}async function* g3() { // Can use yield* on both async and sync iterators yield* g1(); yield* g2();}const gen = g3();console.log(await gen.next()); // {value: "foo", done: false}console.log(await gen.next()); // {value: "bar", done: false}console.log(await gen.next()); // {done: true}Methodenweiterleitung
Dienext(),throw(), undreturn()-Methoden des aktuellen Generators werden alle an den zugrunde liegenden Iterator weitergeleitet.
const iterable = { [Symbol.iterator]() { let count = 0; return { next(v) { console.log("next called with", v); count++; return { value: count, done: false }; }, return(v) { console.log("return called with", v); return { value: "iterable return value", done: true }; }, throw(v) { console.log("throw called with", v); return { value: "iterable thrown value", done: true }; }, }; },};function* gf() { yield* iterable; return "gf return value";}const gen = gf();console.log(gen.next(10));// next called with undefined; the argument of the first next() call is always ignored// { value: 1, done: false }console.log(gen.next(20));// next called with 20// { value: 2, done: false }console.log(gen.return(30));// return called with 30// { value: 'iterable return value', done: true }console.log(gen.next(40));// { value: undefined, done: true }; gen is already closedconst gen2 = gf();console.log(gen2.next(10));// next called with undefined// { value: 1, done: false }console.log(gen2.throw(50));// throw called with 50// { value: 'gf return value', done: true }console.log(gen.next(60));// { value: undefined, done: true }; gen is already closedFalls diereturn()/throw()-Methode des zugrunde liegenden Iteratorsdone: false zurückgibt, wird der aktuelle Generator weiter ausgeführt undyield* delegiert weiterhin an den zugrunde liegenden Iterator.
const iterable = { [Symbol.iterator]() { let count = 0; return { next(v) { console.log("next called with", v); count++; return { value: count, done: false }; }, return(v) { console.log("return called with", v); return { value: "iterable return value", done: false }; }, }; },};function* gf() { yield* iterable; return "gf return value";}const gen = gf();console.log(gen.next(10));// next called with undefined// { value: 1, done: false }console.log(gen.return(20));// return called with 20// { value: 'iterable return value', done: false }console.log(gen.next(30));// { value: 2, done: false }; gen is not closedFalls der zugrunde liegende Iterator keinethrow()-Methode hat und diethrow()-Methode des Generators aufgerufen wird, wirftyield* einen Fehler.
const iterable = { [Symbol.iterator]() { let count = 0; return { next(v) { count++; return { value: count, done: false }; }, }; },};function* gf() { yield* iterable; return "gf return value";}const gen = gf();gen.next(); // First next() starts the yield* expressiongen.throw(20); // TypeError: The iterator does not provide a 'throw' method.Spezifikationen
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-generator-function-definitions-runtime-semantics-evaluation> |