内容:
- I.実配列の列挙
- ForEachメソッドと関連メソッド
- forループ
- for ...の適切な使用
- for ... ofループ(反復子の暗黙的な使用)
- イテレータの明示的な使用
- II。 配列のようなオブジェクトの繰り返し
- メソッドを使用して実際の配列を反復処理する
- 実配列への変換
- ランタイムオブジェクトに関する注意
I.実配列の列挙
現在、実際の配列の要素を反復処理する方法は3つあります。
Array.prototype.forEachメソッド;- 古典的な
forループ - ループ内
for...in 「正しく」構築さfor...in 。
また、まもなく、新しいECMAScript 6(ES 6)標準の出現により、さらに2つの方法が期待されます。
for...ofループ(反復子の暗黙的な使用);- イテレータの明示的な使用。
1. forEachメソッドと関連メソッド
プロジェクトがECMAScript 5(ES5)標準の機能をサポートするように設計されている場合、その革新の1つである
forEachメソッドを使用できます。
使用例:
var a = ["a", "b", "c"]; a.forEach(function(entry) { console.log(entry); });
一般的に、
forEachを使用するには、このメソッドをネイティブにサポートしていないブラウザー用に
es5-shimエミュレーションライブラリを接続する必要があります。 これらにはIE 8以前が含まれ、これらは今でもあちこちで使用されています。
forEachの利点は、配列の現在の要素のインデックスと値を格納するローカル変数を引数として自動的にコールバック関数(コールバック)に渡すため、ローカル変数を宣言する必要がないことです。
アイテムごとにコールバックを呼び出すことで発生する可能性のあるコストを心配している場合は、心配しないで
これを読んでください。
forEach 、配列のすべての要素を反復処理するように設計されていますが、それに加えて、ES5では、すべてまたは一部の要素を反復処理し、それらを使用してアクションを実行するためのいくつかのより便利なメソッドを提供しています:
- every-配列の各要素に対してコールバックが
true変換される値を返す場合、 trueを返しtrue 。 - some-配列の少なくとも1つの要素に対してコールバックが
trueに変換できる値を返す場合、 trueを返しtrue 。 - filter-コールバックが
true返す元の配列の要素を含む、新しい配列を作成しtrue 。 - map-コールバックによって返された値で構成される新しい配列を作成します。
reduce配列を単一の値に縮小し、最初からコールバックを配列の各要素に順番に適用します(配列の要素と他の結果の関数の合計を計算するのに役立ちます)。reduceRight -reduceと同様に機能しますが、要素を逆順にreduceRightます。
2. forループ
去勢牛for古き良き :
var a = ["a", "b", "c"]; var index; for (index = 0; index < a.length; ++index) { console.log(a[index]); }
配列全体の長さがサイクル全体で変化せず、サイクル自体がパフォーマンスの点で重要なコードセグメントに属している場合(これはほとんどありません)、
for 「より最適な」バージョンを
forして配列の長さを格納できます。
var a = ["a", "b", "c"]; var index, len; for (index = 0, len = a.length; index < len; ++index) { console.log(a[index]); }
理論的には、このコードは前のコードよりも少し速く実行されるはずです。
要素を列挙する順序が重要でない場合は、最適化の観点からさらに進んで、列挙の順序を反対に変更することで、配列の長さを格納する変数を取り除くことができます。
var a = ["a", "b", "c"]; var index; for (index = a.length - 1; index >= 0; --index) { console.log(a[index]); }
ただし、最新のJavaScriptエンジンでは、このような最適化されたゲームは通常何の意味もありません。
3. for ...の適切な使用
for...inループを使用することをお勧めする場合、
配列の列挙は意図したものではないことに注意
for...inください。 一般的な誤解に反して、
for...inループは配列インデックスではなく、オブジェクトの列挙プロパティを反復処理します。
ただし、以下の例に示すように、予防措置を講じる場合は、
スパース配列の列挙などの一部のケースで
for...inが役立つ場合があります。
この例では、ループの各反復で、2つのチェックが実行されます。
- 配列には、
keyと呼ばれる独自のプロパティがありkey (プロトタイプからは継承されません)。 - その
keyは、値が4294967294より小さい整数の10進表記を含む文字列です。 最後の数字はどこから来たのですか? ES5の配列インデックスの定義から 、配列の要素が持つことができる最大のインデックスは(2^32 - 2) = 4294967294です。
もちろん、このようなチェックはサイクルの実行中に余分な時間がかかります。 ただし、スパース配列の場合、このメソッドは
forループよりも効率的です。この場合、配列で明示的に定義されている要素のみがソートされるためです。 したがって、上記の例では、3つの反復のみが実行されます(インデックス0、10、および10000)-forループの10001に対して。
配列を反復処理する必要があるたびにこのような面倒な検証コードを記述しないようにするには、別の関数として設計できます。
function arrayHasOwnIndex(array, key) { return array.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294; }
次に、例のサイクルの本体が大幅に削減されます。
for (key in a) { if (arrayHasOwnIndex(a, key)) { console.log(a[key]); } }
上記の検証コードは万能であり、すべての場合に適しています。 しかし、代わりに、正式なもので完全に正しいものではありませんが、より短いバージョンを使用できますが、それでもほとんどの場合に適しています:
for (key in a) { if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) { console.log(a[key]); } }
4. for ...ループ(反復子の暗黙的な使用)
ES6はまだ
ドラフトの状態ですが、JavaScriptでイテレーターを導入する必要があります。
反復子は、値のシーケンス(有限または無限)を取得する標準的な方法を定義するオブジェクトによって実装されるプロトコルです。
イテレータは、
next()メソッドが定義されているオブジェクトです。2つのプロパティを持つオブジェクトを返す引数のない関数です。
done ( boolean )-イテレータが反復可能なシーケンスの最後に到達した場合はtrue それ以外の場合はfalseです。- value-反復子によって返される値を定義します。
doneプロパティがtrue場合、定義されない(存在しない)場合がありtrue 。
を含む多くの組み込みオブジェクト 実配列にはデフォルトの反復子があります。 実際の配列でイテレータを使用する最も簡単な方法は、新しい
for...of構文を使用する
for...of 。
for...ofの使用例:
var val; var a = ["a", "b", "c"]; for (val of a) { console.log(val); }
上記の例では
for...ofループの
for...of Arrayオブジェクトの反復子を暗黙的に呼び出して、配列の各値を取得します。
5.イテレータの明示的な使用
イテレータは明示的に使用することもできますが、この場合、コードは
for...ofループに比べてはるかに複雑になります。 次のようになります。
var a = ["a", "b", "c"]; var it = a.entries(); var entry; while (!(entry = it.next()).done) { console.log(entry.value[1]); }
この例では、
Array.prototype.entriesメソッドは、配列の値を出力するために使用される反復子を返します。 各反復で、
entry.valueは
[, ]形式の配列が含まれます。
II。 配列のようなオブジェクトの繰り返し
実際の配列に加えて、JavaScriptには
配列のようなオブジェクトもあり
ます 。 実際の配列では、
lengthプロパティと、配列の要素に対応する数字の形式の名前を持つプロパティを持つという事実によって関連付けられます。 例は、
NodeListコレクションのDOMと、関数/メソッド内でアクセス可能な
arguments pseudo-
NodeListです。
1.実際の配列を列挙する方法を使用する
少なくともすべてではありませんが、実際の配列を列挙する方法を使用して、配列のようなオブジェクトを列挙できます。
forおよび
for...inコンストラクトは、実際の配列とまったく同じ方法で配列のようなオブジェクトに適用できます。
forEachおよびその他の
Array.prototypeメソッド
Array.prototype 、配列のようなオブジェクトにも適用できます。 これを行うには、
Function.callまたは
Function.applyの呼び出しを使用します。
たとえば、
forEachを
Nodeオブジェクトの
childNodesプロパティに適用する場合、これは次のように行われます。
Array.prototype.forEach.call(node.childNodes, function(child) {
この手法を再利用するために、別の変数で
Array.prototype.forEachメソッドへの参照を宣言し、それを短縮形として使用できます。
配列のようなオブジェクトに反復子がある場合、それを明示的または暗黙的に使用して、実際の配列と同じ方法でオブジェクトを反復処理できます。
2.実配列に変換します
配列のようなオブジェクトを反復処理する別の非常に簡単な方法もあります。それを実際の配列に変換し、上記の方法を使用して実際の配列を反復処理します。 変換には、汎用メソッド
Array.prototype.slice使用できます。これは、任意の配列のようなオブジェクトに適用できます。 以下の例に示すように、これは非常に簡単に行われます。
var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
たとえば、
NodeListコレクションを実際の配列に変換するには、次のようなものが必要です。
var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);
更新 :
ES6の
Array.prototype.slice代わりに
ES6で
rockと
torbasowが指摘したように、より直感的な
Array.fromメソッドを使用できます。
3.ランタイムオブジェクトに関する注意
Array.prototypeメソッドを
Array.prototypeオブジェクト(DOMコレクションなど)に適用する場合、これらのメソッドの正しい動作がすべてのランタイム環境(ブラウザーを含む)で保証されるわけではないことに注意してください。 特定のランタイムでの特定のオブジェクトの動作、より正確には、このオブジェクトで
HasProperty抽象操作がどのように実装されるかに
HasPropertyます。 問題は、ES5標準自体が、この操作に関してオブジェクトの不正な動作の可能性を許可していることです(
§8.6.2を参照)。
したがって、アプリケーションを使用する予定の各ランタイム(ブラウザー)で
Array.prototypeメソッドの動作をテストすることが重要です。