ホームページ ウェブフロントエンド jsチュートリアル JavaScript ジェネレーター: 一時停止機能でコードを強化しましょう!

JavaScript ジェネレーター: 一時停止機能でコードを強化しましょう!

Dec 30, 2024 pm 10:29 PM

JavaScript Generators: Supercharge Your Code with Pausing Power!

JavaScript ジェネレーターは非常に優れています。これらは通常の機能に似ていますが、スーパーパワーが備わっています。私は最近これらを頻繁に使用していますが、コード内の制御フローについての考え方が変わりました。

基本から始めましょう。ジェネレーターは、一時停止および再開できる機能です。 function* 構文と yield キーワードを使用します。簡単な例を次に示します:

function* countToThree() {
  yield 1;
  yield 2;
  yield 3;
}

const counter = countToThree();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
ログイン後にコピー
ログイン後にコピー

関数を一度に 1 つの結果ずつステップ実行する方法がわかりましたか?それがジェネレーターの魔法です。

しかし、ジェネレーターは単にカウントするだけではありません。これらはカスタム反復子の作成に最適です。フィボナッチ数列を生成したいとします:

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const fib = fibonacci();
for (let i = 0; i < 10; i++) {
  console.log(fib.next().value);
}
ログイン後にコピー
ログイン後にコピー

このジェネレーターはフィボナッチ数を永遠に生成し続けます。これは無限シーケンスですが、必要な値のみを計算します。

ここで、ジェネレーターの最も優れた点の 1 つである遅延評価について説明します。これらは、要求された場合にのみ値を計算します。これは、大規模なデータセットや複雑な計算の場合に非常に効率的です。

より実践的な例を見てみましょう。大規模なデータセット用のページネーション システムを構築しているとします:

function* paginate(items, pageSize) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

const allItems = Array.from({ length: 100 }, (_, i) => i + 1);
const pageSize = 10;
const pages = paginate(allItems, pageSize);

console.log(pages.next().value); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(pages.next().value); // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
ログイン後にコピー
ログイン後にコピー

このジェネレーターを使用すると、すべてを一度にメモリにロードすることなく、必要に応じてデータのページをフェッチできます。

ジェネレーターは、非同期プログラミングに関しても威力を発揮します。非同期コードを同期コードのように見せ、動作させることができます。 co ライブラリを使用した例を次に示します。

const co = require('co');

function* fetchUserData() {
  const user = yield fetchUser();
  const posts = yield fetchPosts(user.id);
  const comments = yield fetchComments(posts[0].id);
  return { user, posts, comments };
}

co(fetchUserData).then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});
ログイン後にコピー
ログイン後にコピー

このコードは同期的に見えますが、実際には 3 つの非同期呼び出しを行っています。ジェネレーターは、Promise が解決されるまで、各利回りで一時停止します。

ジェネレーターは、共同マルチタスクにも使用できます。複数のジェネレーターを作成し、それらを切り替えて、同時実行をシミュレートできます。

function* task1() {
  yield 'Start task 1';
  yield 'Middle of task 1';
  yield 'End task 1';
}

function* task2() {
  yield 'Start task 2';
  yield 'Middle of task 2';
  yield 'End task 2';
}

function run(tasks) {
  const iterations = tasks.map(task => task());
  while (iterations.length) {
    const [first, ...rest] = iterations;
    const { value, done } = first.next();
    if (!done) {
      console.log(value);
      iterations.push(first);
    }
    iterations.unshift(...rest);
  }
}

run([task1, task2]);
ログイン後にコピー

このコードは 2 つのタスクを交互に実行し、一度に 1 ステップずつ実行します。

ジェネレーターはステートマシンの作成にも最適です。各収量は異なる状態を表すことができます:

function* trafficLight() {
  while (true) {
    yield 'red';
    yield 'green';
    yield 'yellow';
  }
}

const light = trafficLight();
console.log(light.next().value); // red
console.log(light.next().value); // green
console.log(light.next().value); // yellow
console.log(light.next().value); // red
ログイン後にコピー

この信号機は州を無期限に循環し続けます。

ここで、より高度なテクニックについて話しましょう。ジェネレーターの委任により、別のジェネレーターに譲歩することができます:

function* innerGenerator() {
  yield 'inner 1';
  yield 'inner 2';
}

function* outerGenerator() {
  yield 'outer 1';
  yield* innerGenerator();
  yield 'outer 2';
}

const gen = outerGenerator();
console.log(gen.next().value); // outer 1
console.log(gen.next().value); // inner 1
console.log(gen.next().value); // inner 2
console.log(gen.next().value); // outer 2
ログイン後にコピー

yield* 構文は innerGenerator に委譲し、そのすべての値を生成してから、outerGenerator を続行します。

ジェネレーターでのエラー処理についても言及する価値があります。 throw() メソッドを使用して、エラーをジェネレーターにスローできます。

function* errorGenerator() {
  try {
    yield 'Start';
    yield 'Middle';
    yield 'End';
  } catch (error) {
    console.error('Caught:', error);
    yield 'Error handled';
  }
}

const gen = errorGenerator();
console.log(gen.next().value); // Start
console.log(gen.throw(new Error('Oops!')).value); // Caught: Error: Oops!
                                                  // Error handled
ログイン後にコピー

これにより、非常に高度なエラー処理戦略が可能になります。

ジェネレーターはバックトラッキング アルゴリズムの実装にも使用できます。以下は、項目の可能なすべての組み合わせを生成する簡単な例です:

function* countToThree() {
  yield 1;
  yield 2;
  yield 3;
}

const counter = countToThree();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
ログイン後にコピー
ログイン後にコピー

このジェネレーターは、指定されたアイテムの 2 要素の組み合わせをすべて生成します。

ジェネレーターが真に威力を発揮する領域の 1 つは、大量のデータの処理です。必要なものだけを計算する効率的なデータ処理パイプラインを作成できます。これは、大きなファイルを 1 行ずつ処理する例です:

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const fib = fibonacci();
for (let i = 0; i < 10; i++) {
  console.log(fib.next().value);
}
ログイン後にコピー
ログイン後にコピー

このジェネレーターはファイルを 1 行ずつ読み取るため、巨大なファイルを完全にメモリにロードせずに処理できます。

ジェネレーターを使用して、Observable パターンを実装することもできます。簡単な実装は次のとおりです。

function* paginate(items, pageSize) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

const allItems = Array.from({ length: 100 }, (_, i) => i + 1);
const pageSize = 10;
const pages = paginate(allItems, pageSize);

console.log(pages.next().value); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(pages.next().value); // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
ログイン後にコピー
ログイン後にコピー

このジェネレーターはオブザーバーとして機能し、受信した各データを処理します。

ジェネレーターのもう 1 つの優れた使用法は、カスタム制御構造を作成することです。以下は、ジェネレーターを使用した再試行関数の例です。

const co = require('co');

function* fetchUserData() {
  const user = yield fetchUser();
  const posts = yield fetchPosts(user.id);
  const comments = yield fetchComments(posts[0].id);
  return { user, posts, comments };
}

co(fetchUserData).then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});
ログイン後にコピー
ログイン後にコピー

この再試行関数は、指定された関数を最大 maxAttempts 回試行してから、あきらめます。

結論として、ジェネレーターは、より表現力豊かで効率的で保守しやすいコードを作成するのに役立つ JavaScript の強力な機能です。これらは、複雑な制御フローの処理、非同期操作の管理、大規模なデータセットの処理に最適です。最初は少し奇妙に思えるかもしれませんが、コツを掴めば、プロジェクトでそれらを使用するあらゆる種類の創造的な方法が見つかるでしょう。それでは、次の JavaScript プロジェクトでジェネレーターを試してみてください。コードがどれほど簡素化されるかに驚くかもしれません!


私たちの作品

私たちの作品をぜひチェックしてください:

インベスターセントラル | スマートな暮らし | エポックとエコー | 不可解な謎 | ヒンドゥーヴァ | エリート開発者 | JS スクール


私たちは中程度です

Tech Koala Insights | エポックズ&エコーズワールド | インベスター・セントラル・メディア | 不可解な謎 中 | 科学とエポックミディアム | 現代ヒンドゥーヴァ

以上がJavaScript ジェネレーター: 一時停止機能でコードを強化しましょう!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

JavaScriptは学ぶのが難しいですか? JavaScriptは学ぶのが難しいですか? Apr 03, 2025 am 12:20 AM

JavaScriptを学ぶことは難しくありませんが、挑戦的です。 1)変数、データ型、関数などの基本概念を理解します。2)非同期プログラミングをマスターし、イベントループを通じて実装します。 3)DOM操作を使用し、非同期リクエストを処理することを約束します。 4)一般的な間違いを避け、デバッグテクニックを使用します。 5)パフォーマンスを最適化し、ベストプラクティスに従ってください。

JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? Apr 04, 2025 pm 05:09 PM

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は?
または:
Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は? または: Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Apr 04, 2025 pm 05:36 PM

この記事の視差スクロールと要素のアニメーション効果の実現に関する議論では、Shiseidoの公式ウェブサイト(https://www.shisido.co.co.jp/sb/wonderland/)と同様の達成方法について説明します。

JavaScriptの進化:現在の傾向と将来の見通し JavaScriptの進化:現在の傾向と将来の見通し Apr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Apr 04, 2025 pm 05:12 PM

Console.log出力の違いの根本原因に関する詳細な議論。この記事では、Console.log関数の出力結果の違いをコードの一部で分析し、その背後にある理由を説明します。 �...

See all articles