yield* æ¼ç®å
Baseline
Widely available
This feature is well established and works across many devices and browser versions. Itâs been available across browsers since 2016å¹´9æ.
yield* æ¼ç®åã¯ãã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ï¼åæã¾ãã¯éåæï¼å
ã§ä½¿ç¨ã§ããå¥ã® å復å¯è½ãªãã¸ã§ã¯ãï¼Generator ãªã©ï¼ã¸ã®å§ä»»ã«ä½¿ç¨ãããã¨ãã§ãã¾ããéåæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°å
ã§ã¯ãããã«å¥ã®éåæå復å¯è½ãªãã¸ã§ã¯ãï¼AsyncGenerator ãªã©ï¼ã¸ã®å§ä»»ã«ã使ç¨ã§ãã¾ãã
試ãã¦ã¿ã¾ããã
function* func1() {
yield 42;
}
function* func2() {
yield* func1();
}
const iterator = func2();
console.log(iterator.next().value);
// äºæ³ãããçµæ: 42
æ§æ
yield* expression
弿°
expressionçç¥å¯-
å復å¯è½ãªãã¸ã§ã¯ãã§ãã
è¿å¤
ãã®ã¤ãã¬ã¼ã¿ã¼ãéããããã¨ãï¼done ã true ã®ã¨ãï¼ã«è¿ãããå¤ãè¿ãã¾ãã
解説
yield* å¼ã¯ãªãã©ã³ããå復å¦çãããªãã©ã³ããè¿ãããããã®å¤ãçæãã¾ããããã¯ç¾å¨ã®ã¸ã§ãã¬ã¼ã¿ã¼ã®å復å¦çãåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã«å§ä»»ãã¾ãããããããããããã¸ã§ãã¬ã¼ã¿ã¼ãã¨ãã¤ãã¬ã¼ã¿ã¼ãã¨å¼ã³ã¾ãã yield* ã¯æåã®ããªãã©ã³ãããã¤ãã¬ã¼ã¿ã¼ããå¾è
ã® [Symbol.iterator]() ã¡ã½ãããå¼ã³åºããã¨ã§åå¾ãã¾ãããã®å¾ãã¸ã§ãã¬ã¼ã¿ã¼ã® next() ã¡ã½ãããå¼ã³åºãããããããã®æç¹ã«ããã¦ã yield* ã¯ã¤ãã¬ã¼ã¿ã¼ã® next() ã¡ã½ãããå¼ã³åºãã¾ãããã®éãã¸ã§ãã¬ã¼ã¿ã¼ã® next() ã¡ã½ãããåãåã£ã弿°ï¼æåã®å¼ã³åºãã§ã¯å¸¸ã« undefinedï¼ã渡ãã¨åæã«ãã¤ãã¬ã¼ã¿ã¼ã® next() ã¡ã½ããããè¿ãããçµæãªãã¸ã§ã¯ãã¨åããã®ãyieldãã¾ããã¤ãã¬ã¼ã¿ã¼ã®çµæã done: true ãæã¤å ´åã yield* å¼ã¯å®è¡ã忢ãããã®çµæã® value ãè¿ãã¾ãã
yield* æ¼ç®åã¯ãç¾å¨ã®ã¸ã§ãã¬ã¼ã¿ã¼ã® throw() ã¡ã½ãã㨠return() ã¡ã½ããããåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã«ã転éãã¾ããç¾å¨ã®ã¸ã§ãã¬ã¼ã¿ã¼ããããã®ã¡ã½ããã®ããããã«ãã£ã¦æ©æã«éããããå ´åãåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã«éç¥ããã¾ããã¸ã§ãã¬ã¼ã¿ã¼ã® throw()/return() ã¡ã½ãããå¼ã³åºãããã¨ãåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã® throw()/return() ã¡ã½ãããåã弿°ã§å¼ã³åºããã¾ããthrow()/return() ã®è¿å¤ã¯ next() ã¡ã½ããã®çµæã¨åæ§ã«å¦çãããã¡ã½ãããä¾å¤ãçºçããå ´åããã®ä¾å¤ã¯ yield* å¼ãã伿ããã¾ãã
åºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã« return() ã¡ã½ããããªãå ´åãyield* å¼ã¯ã䏿忢ããã yield å¼ã§ return() ãå¼ã³åºãã®ã¨åæ§ã«ãreturn æã«å¤æããã¾ãã
åºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã« throw() ã¡ã½ããããªããã°ãããã«ãã yield* 㯠TypeError ãçºçããã¾ãããã ããã¨ã©ã¼ãçºçãããåã«ãåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã® return() ã¡ã½ãããåå¨ããå ´åããããå¼ã³åºããã¾ãã
ä¾
>å¥ã®ã¸ã§ãã¬ã¼ã¿ã«å§ä»»ãã
次ã®ã³ã¼ãã§ã¯ã g1() ã«ãã£ã¦çæãããå¤ã¯ã g2() ã§çæããããã®ã¨åãããã« next() ã®å¼ã³åºãããè¿ããã¾ãã
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}
ä»ã®å復å¯è½ãªãªãã¸ã§ã¯ã
ã¸ã§ãã¬ã¼ã¿ãªãã¸ã§ã¯ãã®ã»ãã«ã yield* ã¯ä»ã®ç¨®é¡ã®å復 (ä¾ãã°ãé
åãæååã arguments ãªãã¸ã§ã¯ã) ã yield ãããã¨ãã§ãã¾ãã
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}
yield* å¼èªä½ã®å¤
yield* ã¯å¼ã§ãããæã§ã¯ããã¾ããããã®ãããå¤ã«è©ä¾¡ããã¾ãã
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 㯠falseã g5 ãçµäºãã g4 ã ããçµäºãã¦ãããã
console.log(gen.next()); // {value: 'foo', done: true}
éåæã¸ã§ãã¬ã¼ã¿ã¼ã¨ã®ä½¿ç¨
async function* g1() {
await Promise.resolve(0);
yield "foo";
}
function* g2() {
yield "bar";
}
async function* g3() {
// yield* ã¯éåæã¨åæã®ä¸¡æ¹ã®ã¤ãã¬ã¼ã¿ã¼ã§ä½¿ç¨ã§ãã¾ã
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}
ã¡ã½ããã®è»¢é
ç¾å¨ã®ã¸ã§ãã¬ã¼ã¿ã¼ã® next()ãthrow()ãreturn() ã¡ã½ããã¯ãã¹ã¦ãåºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã«è»¢éããã¾ãã
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 㯠undefined ã§å¼ã³åºããããæåã® next() å¼ã³åºãã®å¼æ°ã¯å¸¸ã«ç¡è¦ããã
// { 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 ã¯æ¢ã«éãã¦ãã
const 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 ã¯æ¢ã«éãã¦ãã
åºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã® return()/throw() ã¡ã½ããã done: false ãè¿ããå ´åã¯ãç¾å¨ã®ã¸ã§ãã¬ã¼ã¿ã¼ã¯å®è¡ãç¶ãã¦ã yield* ã¯åºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã®å§ä»»ãç¶ãã¾ãã
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 closed
åºç¤ã¨ãªãã¤ãã¬ã¼ã¿ã¼ã« throw() ã¡ã½ããããªããã¸ã§ãã¬ã¼ã¿ã¼ã® throw() ãå¼ã³åºãããå ´åã yield* ã¯ã¨ã©ã¼ãçºçãã¾ãã
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* expression
gen.throw(20); // TypeError: The iterator does not provide a 'throw' method.
仿§æ¸
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-generator-function-definitions-runtime-semantics-evaluation> |