ジェネレーターは JavaScript の最も強力な機能の 1 つであり、必要に応じて一時停止および再開できるコードを作成できます。すべてのコードを一度に実行する通常の関数とは異なり、ジェネレーターは遅延実行を使用し、値を段階的に返すため、データ シーケンス、反復、または長時間実行プロセスの操作が容易になります。
JavaScript では、ジェネレーターは function* キーワードを使用して定義され、yield キーワードと組み合わせて、関数を部分的に実行できます。ジェネレーター関数を呼び出すたびに、すぐには実行されませんが、制御された実行を可能にするイテレーターが返されます。
例:
const id = (function* () { let i = 1; while (true) { yield i; i += 1; } })();
この例では、ファンクション ジェネレーターは無限の数値シーケンスを返します。各数値は必要な場合にのみ生成され、返されます。
yield キーワードはジェネレーターの実行を停止し、値を外部に返します。次の関数呼び出し (next() を使用) で、ジェネレーターは中断したところから続行します。
ジェネレーターの呼び出しは次のようになります:
console.log(id.next().value); // 1 console.log(id.next().value); // 2 console.log(id.next().value); // 3
next() を呼び出すたびに、配列の次の値が返され、次の生成時に関数が一時停止されます。
怠惰:
ジェネレーターはすべてを一度に実行するのではなく、必要なときにのみ値を生成します。これは、無限のシーケンスや大規模なデータ配列を扱う場合に最適です。
フロー制御:
関数を一時停止および再開できるため、長時間実行されるプロセスをより適切に制御できます。
効率:
すべての値をメモリに保存するのではなく、ジェネレータは一度に 1 つを返すため、メモリの消費量が削減されます。
ジェネレーターは便利ですが、いくつかの潜在的な問題があります。
複雑なフロー制御:
一時停止と再開を行うと、特に複雑なシナリオの場合、コードの理解とデバッグが困難になる可能性があります。
パフォーマンス:
場合によっては、コードを一時停止して再開すると追加のオーバーヘッドが発生し、効率が低下する可能性があります。
限定:
呼び出しごとに 1 つの値が返されるため、一度に大量のデータにアクセスする必要がある場合は非効率的になる可能性があります。
互換性:
ジェネレーターは ECMAScript 2015 (ES6) 標準の一部であるため、古いブラウザでは Babel などの追加ツールがないとジェネレーターをサポートできない可能性があります。
ジェネレーターが複雑すぎる場合は、代替手段を検討できます。
コールバックを伴う再帰関数:
function generateID(callback, start = 1) { callback(start); setTimeout(() => generateID(callback, start + 1), 0); }
利点:
より簡単なフロー制御: この関数は再帰を使用していますが、プログラムのフロー制御という点では、より読みやすく、明確です。
非同期実行: setTimeout を使用すると非同期操作が有効になり、パフォーマンスの維持に役立ちます。
欠点:
再帰のオーバーヘッド: 反復回数が非常に多い場合、再帰の問題 (スタック オーバーフロー) が発生する可能性があります。
ループ:
所定の数の値を生成する単純なループは、配列が小さい場合にはより効率的なオプションとなる可能性があります。
function generateIDs(limit) { const ids = []; for (let i = 1; i <= limit; i++) { ids.push(i); } return ids; } const ids = generateIDs(100); // Generiše prvih 100 ID-eva console.log(ids);
利点:
シンプルな実装: このソリューションは理解しやすく、フロー制御に問題はありません。
高速生成: すべての値が一度に生成されるため、反復回数が少なくなり、より効率的になります。
欠点:
メモリ消費量: すべての値はメモリに保存されるため、大規模な配列では問題が発生する可能性があります。
怠惰なし: すべての ID が事前に生成されるため、すべてが必要でない場合は非効率的になる可能性があります。
反復子:
.next() メソッドを通じて反復可能な値を返すオブジェクト。ジェネレーターに似ていますが、より詳細な制御が可能です。
function createIDIterator() { let i = 1; return { next() { return { value: i++, done: false }; } }; } const idIterator = createIDIterator(); console.log(idIterator.next().value); // 1 console.log(idIterator.next().value); // 2 console.log(idIterator.next().value); // 3
利点:
フロー制御: ジェネレーターと同様の機能がありますが、実行はより直線的です。
よりシンプルなコード: イールドがないため、コードを理解しやすくなります。
欠点:
自動一時停止なし: 繰り返しを手動で管理する必要があり、場合によっては不便になる可能性があります。
async/await による非同期生成
ID が非同期で生成される場合は、Promise を返す関数で async/await を使用できます。
async function generateID(start = 1) { let i = start; while (true) { await new Promise((resolve) => setTimeout(resolve, 0)); console.log(i++); } } generateID();
利点:
非同期実行: 実行のメイン フローをブロックすることなく、長時間実行される操作を効率的に処理します。
最新の構文: async/await は、非同期コードを操作するためのより現代的で直感的な方法です。
欠点:
同期コードには適していません: 同期生成が必要な場合、このソリューションは理想的ではありません。
ジェネレーターは、大規模で無限のデータ配列を操作したり、プロセスの一時停止と再開が必要なアプリケーションのフロー制御に優れたツールです。ただし、その複雑さとパフォーマンス上の問題が発生する可能性があるため、使用には注意が必要です。アプリケーションの要件によっては、反復、再帰、非同期コードなどの代替ソリューションの方が適切な場合があります。
以上がJavaScript ジェネレーターを理解する: 強力なコード フロー制御ツールの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。