検索
ホームページウェブフロントエンドjsチュートリアルJavaScript_javascript スキルにおけるイテレータとジェネレータの詳細な説明

コレクション内の各項目の処理は、非常に一般的な操作です。JavaScript では、単純な for ループや for each ループから、map()、filter()、配列内包表記まで、コレクションを反復処理するためのさまざまな方法が提供されています。 JavaScript 1.7 では、イテレーターとジェネレーターにより、コア JavaScript 構文に新しい反復メカニズムが導入され、for...in および for each ループの動作をカスタマイズするメカニズムも提供されます。

イテレーター

反復子は、コレクション シーケンス内の 1 つの要素に一度にアクセスし、シーケンス内の反復の現在位置を追跡するオブジェクトです。 JavaScript では、イテレータは、シーケンス内の次の要素を返す next() メソッドを提供するオブジェクトです。このメソッドは、シーケンス内のすべての要素が走査されると StopIteration 例外をスローします。

イテレータ オブジェクトが作成されると、 next() を繰り返し呼び出すことによって明示的に呼び出すか、JavaScript の for...in および for each ループを暗黙的に使用して呼び出すことができます。

オブジェクトと配列を反復処理するための単純なイテレータは、Iterator() を使用して作成できます。

コードをコピーします コードは次のとおりです:

var lang = { 名前: 'JavaScript'、誕生年: 1995 };
var it = Iterator(lang);

初期化が完了すると、 next() メソッドを呼び出して、オブジェクトのキーと値のペアに順番にアクセスできます。

コードをコピーします コードは次のとおりです:

var par = it.next() //キーと値のペアは ["name", "JavaScript"]
です。 par = it.next(); //キーと値のペアは ["誕生日", 1995]
ペア = it.next(); // `StopIteration` 例外がスローされます

next() メソッドを明示的に呼び出す代わりに、for…in ループを使用できます。 StopIteration 例外がスローされると、ループは自動的に終了します。

コードをコピーします コードは次のとおりです:

var it = Iterator(lang);
for (その中の var ペア)
Print(pair); //毎回 1 つの [key, value] キーと値のペアを出力します

オブジェクトのキー値のみを反復したい場合は、値 true を指定して 2 番目のパラメーターを Iterator() 関数に渡すことができます。

コードをコピーします コードは次のとおりです:

var it = Iterator(lang, true);
for (var キーが入っています)
Print(key); //キー値を毎回出力します

Iterator() を使用してオブジェクトにアクセスする利点の 1 つは、Object.prototype に追加されたカスタム プロパティがシーケンス オブジェクトに含まれないことです。

Iterator() は配列でも使用できます:

コードをコピーします コードは次のとおりです:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterator(langs);
for (その中の var ペア)
print(pair); //各反復は [index, language] キーと値のペアを出力します

オブジェクトを走査するのと同じように、2 番目のパラメーターとして true を渡すと、走査は配列インデックスになります。

コードをコピーします コードは次のとおりです:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterator(langs, true);
for (変数 i が含まれています)
print(i) // 0、次に 1、次に 2 を出力します
;

let キーワードを使用して、ループ内のブロック変数にインデックスと値を割り当てます。また、分割代入も使用できます。

コードをコピーします コードは次のとおりです:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterators(langs);
for ([i, lang] を入れます)
print(i ': ' lang) //「0: JavaScript」などを出力

カスタム反復子を宣言します

要素のコレクションを表すオブジェクトは、指定された方法で反復処理される必要があります。

1. 範囲を表すオブジェクトを反復すると、その範囲に含まれる数値を 1 つずつ返します。
2. ツリーのリーフ ノードには、深さ優先または幅優先
を使用してアクセスできます。 3. データベース クエリの結果を表すオブジェクトを反復処理すると、結果セット全体が単一の配列にロードされていない場合でも、行ごとに返される必要があります
4. 無限の数学的シーケンス (フィボナッチ数列など) に作用する反復子は、無限長のデータ構造を作成せずに結果を次々に返す必要があります

JavaScript を使用すると、カスタムの反復ロジックを作成し、それをオブジェクトに適用できます

下限値と上限値を含む単純な Range オブジェクトを作成します。

コードをコピーします コードは次のとおりです:

関数範囲(低、高){
This.low = 低い;
This.high = 高い;
}

ここで、範囲内のすべての整数を含むシーケンスを返すカスタム反復子を作成します。イテレータ インターフェイスでは、シーケンス内の次の要素を返すか、StopIteration 例外をスローする next() メソッドを提供する必要があります。

コードをコピーします コードは次のとおりです:

関数 RangeIterator(range){
This.range = 範囲;
this.current = this.range.low;
}
RangeIterator.prototype.next = function(){
If (this.current > this.range.high)
throw StopIteration;
その他
return this.current ;
};

RangeIterator は範囲インスタンスでインスタンス化され、現在のシーケンス位置を追跡するために現在のプロパティを維持します。

最後に、RangeIterator を Range と組み合わせるために、Range に特別な __iterator__ メソッドを追加する必要があります。 Range を反復しようとしたときに呼び出され、反復ロジックを実装する RangeIterator インスタンスを返す必要があります。

コードをコピーします コードは次のとおりです:

Range.prototype.__iterator__ = function(){
return new RangeIterator(this);
};

カスタム反復子が完了したら、範囲インスタンスを反復処理できます。

コードをコピーします コードは次のとおりです:

var range = new Range(3, 5);
for (範囲内の変数 i)
print(i) // 3、次に 4、次に 5
を出力します。

ジェネレーター: イテレーターを構築するより良い方法

カスタム反復子は便利なツールですが、内部状態を明示的に維持する必要があるため、作成時には慎重な計画が必要です。

ジェネレーターは非常に強力な関数を提供します。これにより、独自の反復アルゴリズムを含む関数を定義でき、独自の状態を自動的に維持できます。

ジェネレーターは、イテレーターファクトリーとして機能する特別な関数です。関数に 1 つ以上の yield 式が含まれる場合、その関数はジェネレーターと呼ばれます (翻訳者注: Node.js では、それを示すために関数名の前に * を追加する必要もあります)。

注: HTML の

ジェネレーター関数が呼び出されると、関数本体はすぐには実行されず、ジェネレーター - イテレーター オブジェクトを返します。ジェネレーター反復子の next() メソッドが呼び出されるたびに、関数本体が次の yield 式まで実行され、その結果が返されます。関数が終了するか、return ステートメントに遭遇すると、StopIteration 例外がスローされます。

例を使用してよりわかりやすく説明します:

コードをコピーします コードは次のとおりです:

関数 simpleGenerator(){
yield "最初";
yield "2番目";
収量「3 番目」;
for (var i = 0; i yield i;
}

var g = simpleGenerator();
Print(g.next()) //「最初」を出力
Print(g.next()) //「2番目」を出力します
Print(g.next()) //「3 番目」を出力します
Print(g.next()) // 0
を出力します。 Print(g.next()) //出力 1
Print(g.next()) //出力 2
Print(g.next()); //StopIteration 例外をスローします

ジェネレーター関数はクラスで __iterator__ メソッドとして直接使用できるため、カスタム反復子が必要なコードの量を効果的に削減できます。ジェネレーターを使用して Range を書き換えてみましょう:

コードをコピー コードは次のとおりです:

関数範囲(低、高){
This.low = 低い;
This.high = 高い;
}
Range.prototype.__iterator__ = function(){
for (var i = this.low; i yield i;
};
var range = new Range(3, 5);
for (範囲内の変数 i)
print(i) // 3、次に 4、次に 5
を出力します。

すべてのジェネレーターが終了するわけではありません。無限シーケンスを表すジェネレーターを作成できます。次のジェネレーターは、各要素が前の 2 つの要素の合計であるフィボナッチ数列を実装します。

コードをコピー コードは次のとおりです:
関数フィボナッチ(){
var fn1 = 1;
var fn2 = 1;
一方 (1) {
var current = fn2;
fn2 = fn1;
fn1 = 現在の fn1;
降伏電流;
}
}

var シーケンス = fibonacci();
Print(sequence.next()) // 1
Print(sequence.next()) // 1
Print(sequence.next()) // 2
Print(sequence.next()) // 3
Print(sequence.next()) // 5
Print(sequence.next()) // 8
Print(sequence.next()) // 13

ジェネレーター関数はパラメーターを取ることができ、これらのパラメーターは関数が初めて呼び出されるときに使用されます。 return ステートメントを使用すると、ジェネレーターを終了できます (StopIteration 例外をスローします)。 fibonacci() の次のバリアントは、条件がトリガーされたときに関数を終了するオプションの limit 引数を受け取ります。

コードをコピーします コードは次のとおりです:

関数フィボナッチ(制限){
var fn1 = 1;
var fn2 = 1;
while(1){
var current = fn2;
fn2 = fn1;
fn1 = 現在の fn1;
If (限界 && 現在 > 限界)
return;
降伏電流;
}
}

高度なジェネレーター機能

ジェネレーターはオンデマンドで利回りの戻り値を計算できるため、これまで高価だったシーケンス計算要件 (上に示したような無限シーケンスも含む) を表現できるようになります。

ジェネレーター反復子オブジェクトには、next() メソッドに加えて、ジェネレーターの内部状態を変更できる send() メソッドもあります。 send() に渡された値は最後の yield 式の結果として扱われ、ジェネレーターは一時停止されます。 send() メソッドを使用して指定された値を渡す前に、少なくとも 1 回 next() を呼び出してジェネレーターを開始する必要があります。

次のフィボナッチ ジェネレーターは、send() メソッドを使用してシーケンスを再開します。

コードをコピーします コードは次のとおりです:

関数フィボナッチ(){
var fn1 = 1;
var fn2 = 1;
一方 (1) {
var current = fn2;
fn2 = fn1;
fn1 = 現在の fn1;
var リセット = 降伏電流;
if (リセット) {
fn1 = 1;
fn2 = 1;
}
}
}

var シーケンス = fibonacci();
Print(sequence.next()) //1
Print(sequence.next()) //1
Print(sequence.next()) //2
Print(sequence.next()) //3
Print(sequence.next()) //5
Print(sequence.next()) //8
Print(sequence.next()) //13
Print(sequence.send(true)); //1
Print(sequence.next()) //1
Print(sequence.next()) //2
Print(sequence.next()) //3

注: 興味深い点は、send(unknown) の呼び出しは next() の呼び出しとまったく同じであるということです。ただし、send() メソッドを呼び出して新しいジェネレーターを開始する場合、unknown 以外の値を指定すると、TypeError 例外がスローされます。

throw メソッドを呼び出して、スローする必要がある例外値を渡すことで、ジェネレーターに例外をスローさせることができます。この例外は現在のコンテキストからスローされ、現在の yield 実行と同様にジェネレーターを一時停止しますが、throw value ステートメントに置き換えられる点が異なります。

スローされた例外の処理中に yield が発生しない場合、例外は throw() メソッドが呼び出されるまで渡され、その後 next() を呼び出すと StopIteration 例外がスローされます。

ジェネレーターには、ジェネレーターを強制的に終了する close() メソッドがあります。ジェネレーターを終了すると、次のような影響があります:

1. ジェネレーター内のすべての有効なfinally句が実行されます
2.finally 句が StopIteration 以外の例外をスローした場合、その例外は close() メソッドの呼び出し元に渡されます
3. ジェネレーターは終了します

ジェネレーター式

配列内包表記 の明らかな欠点は、配列全体がメモリ内に構築されることです。内包表記への入力が小さい配列である場合、オーバーヘッドはわずかですが、入力配列が大きい場合、または新しい高価な (または無限の) 配列ジェネレーターが作成される場合には、問題が発生する可能性があります。

ジェネレーターを使用すると、シーケンスの遅延計算が可能になり、必要に応じて要素をオンデマンドで計算できます。ジェネレーター式は構文的には配列内包表記とほぼ同じです。角括弧の代わりに括弧を使用します (for each...in の代わりに for...in)。ただし、配列の代わりにジェネレーターを作成するため、計算を遅らせます。これは、ジェネレーターを作成するための短い構文と考えることができます。

巨大な整数シーケンスを反復処理する反復子があるとします。偶数を反復するには新しい反復子を作成する必要があります。配列内包表記では、すべての偶数からなる配列全体がメモリ内に作成されます:

コードをコピー コードは次のとおりです:

var doubles = [i * 2 for (i in it)];

ジェネレータ式は新しいイテレータを作成し、必要に応じてオンデマンドで偶数の値を計算します。

コードをコピー コードは次のとおりです:

var it2 = (i * 2 for (i in it));
Print(it2.next()) //その中の最初の偶数
Print(it2.next()) //その中の 2 番目の偶数

ジェネレーターが関数の引数として使用される場合、関数呼び出しに括弧が使用されます。つまり、最も外側の括弧は省略できます。

コードをコピーします コードは次のとおりです:

var result = doSomething(i * 2 for (i in it));

終了

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
CおよびJavaScript:接続が説明しましたCおよびJavaScript:接続が説明しましたApr 23, 2025 am 12:07 AM

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

Webサイトからアプリまで:JavaScriptの多様なアプリケーションWebサイトからアプリまで:JavaScriptの多様なアプリケーションApr 22, 2025 am 12:02 AM

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Python vs. JavaScript:ユースケースとアプリケーションと比較されますPython vs. JavaScript:ユースケースとアプリケーションと比較されますApr 21, 2025 am 12:01 AM

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

JavaScript通訳者とコンパイラにおけるC/Cの役割JavaScript通訳者とコンパイラにおけるC/Cの役割Apr 20, 2025 am 12:01 AM

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

JavaScript in Action:実際の例とプロジェクトJavaScript in Action:実際の例とプロジェクトApr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

See all articles

ホット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 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。