HTML: Markup language
CSS: Styling language
JavaScript: Scripting language
Web APIs: Programming interfaces
All web technology
Learn web development
Discover our tools
Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
View in English Always switch to English
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2016年9月.
function* 宣言は、新しいジェネレーター関数を指定された名前へのバインドとして作成します。ジェネレーター関数は、脱出した後でそのコンテキスト(変数のバインド)を保存したまま再入することが可能です。
function*
ジェネレーター関数は function* 式を使って定義することもできます。
function* generator(i) { yield i; yield i + 10; } const gen = generator(10); console.log(gen.next().value); // 予想される結果: 10 console.log(gen.next().value); // 予想される結果: 20
function* name(param0) { statements } function* name(param0, param1) { statements } function* name(param0, param1, /* …, */ paramN) { statements }
メモ: ジェネレーター関数には、対応するアロー関数はありません。
メモ: function と * は別々なトークンなので、ホワイトスペースまたは改行で区切ることが可能です。
function
*
name
関数名。
param
関数の形式上の引数の名前。引数の構文については、関数リファレンスを参照してください。
statements
関数の本体を構成する文。
function* 宣言は GeneratorFunction オブジェクトを生成します。ジェネレーター関数が呼び出されるたびに、新しい Generator オブジェクトが返され、これはイテレータープロトコルに準拠します。ジェネレーター関数の実行は、ある場所で中断されます。初期状態では関数本体の先頭で中断されます。ジェネレーター関数は複数回呼び出して複数のジェネレーターを同時に生成できます。各ジェネレーターは、ジェネレーター関数の実行コンテキストを独自に保持し、独立してステップ実行できます。
GeneratorFunction
Generator
ジェネレーターは双方向の制御フローをすることができます。制御フローはジェネレーター関数(呼び出し先)とその呼び出し側の間で、双方が望む回数だけ移行できます。制御フローは呼び出し側から呼び出し先へ、ジェネレーターのメソッド、next()、throw()、return() を呼んで移行します。制御フローは、return や throw を使用して通常通り関数を終了させたり、すべての文を実行したり、yield および yield* 式を使用したりすることで、呼び出し側から呼び出し先へ進むことができます。
next()
throw()
return()
return
throw
yield
yield*
ジェネレーターの next() メソッドが呼び出されると、ジェネレーター関数の本体は次のいずれかになるまで実行されます。
value
false
done
try...catch...finally
return undefined
true
{ value: undefined, done: true }
ジェネレーターの throw() メソッドが呼び出されると、現在の中断位置でジェネレーターの本体に throw 文が挿入されたかのように動作します。同様に、ジェネレーターの return() メソッドが呼び出されると、現在の中断位置に return 文が挿入されたかのように動作します。どちらのメソッドも、ジェネレーター関数が try...catch...finally によって完了をキャッチしない限り、通常はジェネレーターを完了させます。
ジェネレーターはかつて非同期プログラミングのパラダイムであり、コールバック地獄を制御の反転によって避けることができました。現在では、この場合の解決はよりシンプルな async 関数モデルと Promise オブジェクトで解決されています。しかし、ジェネレーターは依然として他の多くのタスク、例えばイテレーターを直感的に定義するといった用途で有用です。
Promise
function* 宣言は function 宣言と同様の挙動を示します。これらはスコープの先頭に巻き上げられ、そのスコープ内のどこでも呼び出せます。また、特定のコンテキストでのみ再宣言が可能です。
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 // …
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
function* logGenerator() { console.log(0); console.log(1, yield); console.log(2, yield); console.log(3, yield); } const gen = logGenerator(); // 最初の next の呼び出しで、関数の最初から、 // 最初の yield 文の前まで実行される。 gen.next(); // 0 gen.next("pretzel"); // 1 pretzel gen.next("california"); // 2 california gen.next("mayonnaise"); // 3 mayonnaise
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 }
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 }
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 }
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' ]
function* f() {} const obj = new f(); // throws "TypeError: f is not a constructor
function* powers(n) { // 生成の無限ループ for (let current = n; ; current *= n) { yield current; } } for (const power of powers(2)) { // ジェネレーターを制御 if (power > 32) { break; } console.log(power); // 2 // 4 // 8 // 16 // 32 }
Enable JavaScript to view this browser compatibility table.
async function
async function*