ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript_javascript スキルにおけるイテレータとジェネレータの詳細な説明

JavaScript_javascript スキルにおけるイテレータとジェネレータの詳細な説明

WBOY
WBOYオリジナル
2016-05-16 16:32:521429ブラウズ

コレクション内の各項目の処理は、非常に一般的な操作です。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 の