web-dev-qa-db-ja.com

JavaScriptで配列のそれぞれの?

JavaScriptを使用して配列内のすべてのエントリをループする方法を教えてください。

私はそれがこのようなものだと思った:

forEach(instance in theArray)

theArrayは私の配列ですが、これは正しくないようです。

4194
Dante1986

TL; DR

  • for-inは、セーフガードで使用するか、少なくとも噛み付く理由を認識していない限り使用しないでください。
  • 最善の策は通常

    • for-ofループ(ES2015 +のみ)、
    • Array#forEachspec | MDN )(またはその親類someなど)(ES5 +のみ)、
    • シンプルな昔ながらのforループ、
    • またはセーフガード付きのfor-in

しかし、lotsがあります。


JavaScriptには、配列および配列のようなオブジェクトをループするための強力なセマンティクスがあります。私は答えを2つの部分に分けました:純粋な配列のオプション、およびargumentsオブジェクト、その他の反復可能なオブジェクト(ES2015 +)、DOMなどの単なる配列-likeのオプションコレクションなど。

ES2015のオプションnowを、ES5エンジンでもtranspilingES5からES5に使用できることにすぐに気付くでしょう。詳細については、「ES2015 transpiling」/「ES6 transpiling」を検索してください...

さて、オプションを見てみましょう:

実際の配列の場合

ECMAScript 5 ( "ES5")には3つのオプションがあり、現時点で最も広くサポートされているバージョンで、さらに2つが ECMAScript 2015 ( "ES2015"、 "ES6 "):

  1. forEachおよび関連(ES5 +)を使用します
  2. 単純なforループを使用する
  3. for-inを正しく使用する
  4. for-ofを使用します(暗黙的にイテレーターを使用します)(ES2015 +)
  5. イテレータを明示的に使用する(ES2015 +)

詳細:

1. forEachおよび関連を使用します

ES5によって追加されたArray機能に(直接またはポリフィルを使用して)アクセスできる漠然と近代的な環境(つまりIE8ではない)では、forEachを使用できます( spec | MDN ):

var a = ["a", "b", "c"];
a.forEach(function(entry) {
    console.log(entry);
});

forEachはコールバック関数を受け入れ、オプションで、そのコールバックを呼び出すときにthisとして使用する値を受け入れます(上記では使用していません)。コールバックは、配列内の各エントリに対して順番に呼び出され、スパース配列内に存在しないエントリをスキップします。上記の引数は1つしか使用していませんが、コールバックは3つで呼び出されます。各エントリの値、そのエントリのインデックス、繰り返し処理する配列への参照(関数がまだ手元にない場合) )。

IE8(2016年9月の執筆時点でNetAppsがわずか4%の市場シェアを示している)のような古いブラウザーをサポートしていない限り、シムなしの汎用WebページでforEachを喜んで使用できます。廃止されたブラウザをサポートする必要がある場合は、forEachのシミング/ポリフィルを簡単に実行できます(いくつかのオプションについては「es5 shim」を検索してください)。

forEachには、イテレーション関数への引数として提供され、そのイテレーションだけにうまくスコープされるため、包含スコープでインデックス変数と値変数を宣言する必要がないという利点があります。

配列エントリごとに関数呼び出しを実行するランタイムコストが心配な場合は、心配しないでください。 詳細

さらに、forEachは「すべてをループする」関数ですが、ES5では、次のような他の便利な「配列を操作して物事を実行する」関数を定義しています。

  • every (コールバックがfalseまたは何か偽を返す最初のときにループを停止します)
  • some (コールバックがtrueまたは何らかの真実を返す最初のときにループを停止します)
  • filter (フィルター関数がtrueを返す要素を含む新しい配列を作成し、falseを返す要素を省略します)
  • map (コールバックによって返された値から新しい配列を作成します)
  • reduce (コールバックを繰り返し呼び出して値を作成し、以前の値を渡します。詳細については仕様を参照してください。配列の内容や他の多くの内容を合計するのに便利です)
  • reduceRightreduceと同様ですが、昇順ではなく降順で動作します)

2.単純なforループを使用します

古い方法が最良の場合もあります。

var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

ループ中に配列の長さが変化せず、パフォーマンスに敏感なコードである場合(ほとんどありません)、前に長さを取得する少し複雑なバージョンはtinyビット高速化:

var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

および/または逆算:

var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

しかし、最新のJavaScriptエンジンでは、最後の一歩を踏み出す必要はほとんどありません。

ES2015以降では、インデックス変数と値変数をforループに対してローカルにすることができます。

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
    console.log(index, value);
}
//console.log(index);   // would cause "ReferenceError: index is not defined"
//console.log(value);   // would cause "ReferenceError: value is not defined"
let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
    console.log(index, value);
}
try {
    console.log(index);
} catch (e) {
    console.error(e);   // "ReferenceError: index is not defined"
}
try {
    console.log(value);
} catch (e) {
    console.error(e);   // "ReferenceError: value is not defined"
}

そして、それを行うと、valueだけでなくindexも各ループ反復で再作成されます。つまり、ループ本体で作成されたクロージャーは、その特定の反復用に作成されたindex(およびvalue)への参照を保持します:

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        console.log("Index is: " + index);
    });
}
let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        console.log("Index is: " + index);
    });
}
<div>zero</div>
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>

Divが5つある場合、最初をクリックすると「Index is:0」、最後をクリックすると「Index is:4」になります。 varの代わりにletを使用する場合、これはnot動作します。

3. for-inを正しく使用する

for-inを使用するように言われますが、 for-inの目的ではありませんfor-inは、配列のインデックスではなく、オブジェクトの列挙可能なプロパティをループします順序は保証されていません、ES2015(ES6)でも保証されていません。 ES2015 +は、オブジェクトプロパティの順序を定義します( [[OwnPropertyKeys]] 、および [[Enumerate]] 、およびそれらを使用するものは Object.getOwnPropertyKeys )が、それはしないfor-inがその順序に従うことを定義します。 (詳細は この他の回答 で。)

配列上のfor-inの唯一の実際の使用例は次のとおりです。

  • sparsearray withmassivegaps、または
  • 非要素プロパティを使用しており、それらをループに含めたい

最初の例を見てください:適切な保護手段を使用している場合は、for-inを使用してこれらのスペア配列要素にアクセスできます。

// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These checks are
        /^0$|^[1-9]\d*$/.test(key) &&    // explained
        key <= 4294967294                // below
        ) {
        console.log(a[key]);
    }
}

3つのチェックに注意してください。

  1. オブジェクトの名前がownプロパティ(プロトタイプから継承したものではない)を持つこと、および

  2. キーがすべて10進数である(例:科学表記法ではなく、通常の文字列形式)

  3. 数値に強制されたときのキーの値は<= 2 ^ 32-2(4,294,967,294)です。その番号はどこから来たのですか?これは、配列インデックスの定義の一部です 仕様で 。その他の数値(非整数、負の数値、2 ^ 32-2より大きい数値)は配列インデックスではありません。 2 ^ 32-2である理由は、最大のインデックス値を2 ^ 32-よりも1つ低くするためです。 1。これは、配列のlengthが持つことができる最大値です。 (たとえば、配列の長さは32ビットの符号なし整数に収まります。)(コメントで指摘してくれたRobGの小道具 私のブログ投稿 私の以前のテストは完全ではなかった右)

もちろん、インラインコードではそうしません。ユーティリティ関数を作成します。おそらく:

// Utility function for antiquated environments without `forEach`
var hasOwn = Object.prototype.hasOwnProperty;
var rexNum = /^0$|^[1-9]\d*$/;
function sparseEach(array, callback, thisArg) {
    var index;
    for (var key in array) {
        index = +key;
        if (hasOwn.call(a, key) &&
            rexNum.test(key) &&
            index <= 4294967294
            ) {
            callback.call(thisArg, array[key], index, array);
        }
    }
}

var a = [];
a[5] = "five";
a[10] = "ten";
a[100000] = "one hundred thousand";
a.b = "bee";

sparseEach(a, function(value, index) {
    console.log("Value at " + index + " is " + value);
});

4. for-ofを使用します(暗黙的にイテレーターを使用します)(ES2015 +)

ES2015は、JavaScriptにiteratorsを追加します。イテレータを使用する最も簡単な方法は、新しいfor-ofステートメントです。次のようになります。

const a = ["a", "b", "c"];
for (const val of a) {
    console.log(val);
}

内部では、配列からiteratorを取得し、それをループして値を取得します。 for-inを使用するとオブジェクト(配列)で定義されたイテレータを使用し、イテレータがentries(プロパティではなく)を反復処理することを定義するため、これには問題がありません)。 ES5のfor-inとは異なり、エントリがアクセスされる順序はインデックスの番号順です。

5.イテレータを明示的に使用する(ES2015 +)

場合によっては、反復子を明示的に使用することもできます。それもできますが、for-ofよりもかなり不格好です。次のようになります。

const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

イテレータは、仕様のイテレータ定義に一致するオブジェクトです。 nextメソッドは、呼び出すたびに新しいresultオブジェクトを返します。結果オブジェクトには、完了したかどうかを示すプロパティdoneと、その反復の値を持つプロパティvalueがあります。 (donefalseの場合はオプション、valueundefinedの場合はオプションです。)

valueの意味は、イテレーターによって異なります。配列は、反復子を返す(少なくとも)3つの関数をサポートします。

  • values():これは上で使用したものです。それぞれのvalueがその反復の配列エントリであるイテレータを返します(前の例の"a""b"、および"c")。
  • keys():各valueがその反復のキーであるイテレータを返します(上記のaの場合、それは"0""1""2"になります)。
  • entries():各valueがその反復の[key, value]形式の配列であるイテレーターを返します。

配列のようなオブジェクトの場合

真の配列の他に、lengthプロパティと数値名を持つプロパティ(NodeListインスタンス、argumentsオブジェクトなど)を持つarray-likeオブジェクトもあります。それらのコンテンツをどのようにループしますか?

上記のオプションを配列に使用します

上記の配列アプローチの少なくともいくつか、そしておそらくほとんどまたはすべてさえも、配列のようなオブジェクトに頻繁に等しく適用されます。

  1. forEachおよび関連する(ES5 +)を使用します

    Array.prototypeのさまざまな関数は「意図的に汎用」であり、通常は Function#call または Function#apply を介して配列のようなオブジェクトで使用できます。 (この回答の最後にあるホスト提供オブジェクトに関するCaveatを参照してください。ただし、これはまれな問題です。)

    forEachNodeプロパティでchildNodesを使用したいとします。あなたはこれをするでしょう:

    Array.prototype.forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    

    あなたがそれをたくさんやるつもりなら、再利用のために関数参照のコピーを変数に取得したいかもしれません:

    // (This is all presumably in some scoping function)
    var forEach = Array.prototype.forEach;
    
    // Then later...
    forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    
  2. 単純なforループを使用する

    明らかに、単純なforループが配列のようなオブジェクトに適用されます。

  3. for-inを使用する正しく使用する

    for-inは、配列と同じセーフガードを使用して、配列のようなオブジェクトでも機能するはずです。上記の#1のホスト提供オブジェクトの警告が適用される場合があります。

  4. for-ofを使用(暗黙的にイテレータを使用)(ES2015 +)

    for-ofは、オブジェクトが提供するイテレーターを使用します(存在する場合)。さまざまな配列のようなオブジェクト、特にホストが提供するオブジェクトでこれがどのように動作するかを確認する必要があります。たとえば、NodeListからのquerySelectorAllの仕様は、反復をサポートするために更新されました。 HTMLCollectionからのgetElementsByTagNameの仕様はそうではありませんでした。

  5. イテレータを明示的に使用する(ES2015 +)

    #4を参照してください、イテレータがどのように動作するかを確認する必要があります。

真の配列を作成する

また、配列のようなオブジェクトを真の配列に変換したい場合もあります。それは驚くほど簡単です:

  1. slice 配列のメソッドを使用する

    配列のsliceメソッドを使用できます。これは、上記の他のメソッドと同様に「意図的に汎用」であるため、次のように配列のようなオブジェクトで使用できます。

    var trueArray = Array.prototype.slice.call(arrayLikeObject);
    

    したがって、たとえば、NodeListを真の配列に変換する場合は、次のようにします。

    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
    

    以下のホスト提供オブジェクトの警告を参照してください。特に、これはIE8以前では失敗することに注意してください。ホスト提供のオブジェクトをthisとして使用することはできません。

  2. スプレッド構文(...を使用

    この機能をサポートするJavaScriptエンジンでES2015の スプレッド構文 を使用することもできます。

    var trueArray = [...iterableObject];
    

    したがって、たとえばNodeListを真の配列に変換したい場合、スプレッド構文を使用すると、これは非常に簡潔になります。

    var divs = [...document.querySelectorAll("div")];
    
  3. Array.fromを使用 (spec) | (MDN)

    Array.from(ES2015 +、ただし簡単にポリフィル)は、配列のようなオブジェクトから配列を作成し、オプションで最初にマッピング関数にエントリを渡します。そう:

    var divs = Array.from(document.querySelectorAll("div"));
    

    または、特定のクラスを持つ要素のタグ名の配列を取得する場合は、マッピング関数を使用します。

    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });
    

ホストが提供するオブジェクトに関する注意

Array.prototype関数をHost-provided配列のようなオブジェクト(DOMリストおよびJavaScriptエンジンではなくブラウザーによって提供されるその他のもの)で使用する場合、ターゲットでテストする必要がありますホストが提供するオブジェクトが適切に動作することを確認する環境。 ほとんどは正しく動作します(今)、しかしテストすることが重要です。その理由は、使用する可能性が高いArray.prototypeメソッドのほとんどが、抽象 [[HasProperty]] 操作に対する正直な答えを与えるホスト提供のオブジェクトに依存しているためです。この記事の執筆時点では、ブラウザーはこれを非常に上手く行っていますが、5.1仕様では、ホストが提供するオブジェクトが正直でない可能性を考慮していました。それは §8.6.2 にあり、そのセクションの冒頭近くの大きなテーブルの下のいくつかの段落)にあり、次のように書かれています:

ホストオブジェクトは、特に指定がない限り、これらの内部メソッドを任意の方法で実装できます。たとえば、特定のHostオブジェクトの[[Get]]および[[Put]]が実際にプロパティ値をフェッチして保存しますが、[[HasProperty]]は常にfalseを生成する可能性があります。

(ES2015仕様では同等の表現を見つけることができませんでしたが、それは事実です。)繰り返しますが、この記事の執筆時点では、最新のブラウザー[たとえば、NodeListインスタンス]でホストが提供する一般的な配列のようなオブジェクトdo[[HasProperty]]を正しく処理しますが、テストすることが重要です。)

6662
T.J. Crowder

編集 :この答えは絶望的に古くなっています。より現代的なアプローチについては、 配列で利用可能なメソッド をご覧ください。興味のある方法は次のとおりです。

  • forEach
  • 地図
  • フィルタ
  • ジップ
  • 減らす
  • すべての
  • 一部

JavaScript で配列を反復する標準的な方法は、Vanillaのfor-ループです。

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element
}

ただし、この方法は、密な配列があり、各インデックスが要素で占められている場合にのみ有効です。配列が疎である場合、このアプローチではパフォーマンスの問題に遭遇する可能性があります。これは、配列に本当にが存在しない多数のインデックスを反復処理するためです。この場合、for .. in-ループを使用することをお勧めします。 ただし ただし、for..in-ループは従来のブラウザでも列挙されるため、配列の目的のプロパティ(つまり、配列要素)のみが確実に機能するように、適切な保護手段を使用する必要があります。追加のプロパティがenumerableとして定義されている場合.

ECMAScript 5 には配列プロトタイプのforEachメソッドがありますが、それはレガシーブラウザではサポートされていません。それで、それを一貫して使用することができるようにするには、それをサポートする環境(例えば Node.js をサーバーサイドJavaScript用)にするか、 "Polyfill"を使用する必要があります。ただし、この機能のPolyfillは簡単で、コードを読みやすくするため、含めることをお勧めします。

473

jQuery ライブラリを使用している場合は、 jQuery.each を使用できます。

$.each(yourArray, function(index, value) {
  // do your stuff here
});

編集:  

質問によると、ユーザーはjqueryではなくjavascriptのコードが欲しいので、編集は

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}
214
Poonam

後方にループ

ここで、reverseforループに言及する価値があると思います。

for (var i = array.length; i--; ) {
     // process array[i]
}

利点:

  • 一時的なlen変数を宣言したり、各反復でarray.lengthと比較したりする必要はありません。どちらもわずかな最適化です。
  • 兄弟の削除は、DOMから逆の順序で通常はより効率的なです。 (ブラウザは、内部配列の要素の移動を少なくする必要があります。)
  • 配列の変更ループ中、インデックスi以降で(たとえば、array[i]で項目を削除または挿入する)、前方ループはスキップします位置iに左に移動したアイテム、または右に移動したi番目のアイテムを再処理します。従来のforループでは、couldupdateiを処理する必要がある次のアイテムを指すように更新します-1、ただし反復の方向を単に逆にする多くの場合、シンプルおよび よりエレガントなソリューション
  • 同様に、nested DOM要素を変更または削除する場合、逆の処理でcircumvent errorsを実行できます。たとえば、子を処理する前に親ノードのinnerHTMLを変更することを検討してください。子ノードに到達するまでに、DOMから切り離され、親のinnerHTMLが作成されたときに新しく作成された子に置き換えられます。
  • 入力可能なshorter、および利用可能な他のオプションよりもreadです。 forEach()とES6のfor ... ofを失いますが。

短所:

  • アイテムを逆順に処理します。結果から新しい配列を構築したり、画面上に物を印刷したりする場合、当然のことながら、元の順序に関して出力は逆になりますです。
  • 順序を保持するために兄弟を最初の子としてDOMに繰り返し挿入すると、非効率的になります。 (ブラウザは、物事を正しくシフトし続ける必要があります。)DOMノードを効率的かつ順番に作成するには、通常の方法でループフォワードして追加します(「ドキュメントフラグメント」も使用します)。
  • 逆のループは、ジュニア開発者にとってconfusingです。 (Outlookに応じて、その利点を考慮することができます。)

常に使用すべきですか?

一部の開発者は、順方向にループする正当な理由がない限り、デフォルトで逆forループを使用します

パフォーマンスの向上は通常は取るに足らないものですが、それは一種の悲鳴です。

「リスト内のすべてのアイテムにこれを行うだけで、順序は気にしません!」

ただし、実際にはnotは意図の信頼できる指示です。なぜなら、doを気にするときと区別できないためです。順序、そして実際にneedを逆にループします。そのため、実際には、「ドントケア」の意図を正確に表現するために別の構造が必要になります。これは、ECMAScriptを含むほとんどの言語では現在利用できないものですが、たとえばforEachUnordered()と呼ぶことができます。

順序が重要ではなく、効率が懸念事項である場合(ゲームまたはアニメーションエンジンの最も内側のループで)、go-toパターンとしてreverse forループを使用することは許容される場合があります。既存のコードで逆forループが表示されることを覚えておいてください必ずしも意味するわけではありません順序は無関係です!

ForEach()を使用することをお勧めします

一般的に、clarity and safetyがより重要な上位レベルのコードの場合、デフォルトパターンとして Array::forEach を使用することをお勧めします。

  • 読むのは明らかです。
  • これは、iがブロック内でシフトされないことを示します(これは、長いforおよびwhileループ内に常に隠れている可能性があります)。
  • クロージャーの自由な範囲を提供します。
  • ローカル変数の漏洩と、外部変数との偶然の衝突(および突然変異)を減らします。

次に、コード内にforループの逆が表示されている場合、それは正当な理由(おそらく上記の理由の1つ)のために逆になっているというヒントです。また、従来のforループを見ると、シフトが発生している可能性があります。

(意図についての議論が意味をなさない場合、あなたとあなたのコードは Programming Style&Your Brain に関するCrockfordの講義を見ることで恩恵を受けるかもしれません。)


どのように機能しますか?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

i--が中央の句(通常は比較が表示される)であり、最後の句が空(通常はi++が表示される)であることがわかります。つまり、i--は、継続のconditionとしても使用されます。重要なのは、各繰り返しの前に実行され、チェックされることです。

  • 爆発せずにarray.lengthで開始する方法

    i--は各反復でbeforeを実行するため、最初の反復では、実際にarray.length - 1の項目にアクセスし、問題を回避します 配列の範囲外 undefined個のアイテム。

  • インデックス0の前に繰り返し処理を停止しないのはなぜですか?

    ループは、条件i--が偽の値に評価されるとき(0を生成するとき)に反復を停止します。

    トリックは、--iとは異なり、末尾のi--演算子はiをデクリメントしますが、値beforeをデクリメントします。コンソールはこれを実証できます:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    したがって、最後の反復では、iは以前は1であり、i--式はに変更しますが、実際には1(真)なので、条件は成立します。次の反復でi--i-1に変更しますが、(falsey)を生成し、実行がすぐに下からドロップしますループの。

    従来のforループでは、i++++iは交換可能です(Douglas Crockfordが指摘しているように)。ただし、逆ループでは、デクリメントも条件式であるため、インデックス0のアイテムを処理する場合はi--を使用する必要があります。


トリビア

一部の人々は、逆forループに小さな矢印を描き、ウィンクで終わることを好みます:

for (var i = array.length; i --> 0 ;) {

逆forループの利点と恐怖を見せてくれたクレジットはWYLに送られます。

99
joeytwiddle

いくつかの _ c _ - スタイルの言語は列挙をループするためにforeachを使います。 JavaScriptでは、これは for..inループ構造 :で行われます。

var index,
    value;
for (index in obj) {
    value = obj[index];
}

キャッチがあります。 for..inは、オブジェクトの列挙可能な各メンバとそのプロトタイプ上のメンバをループします。オブジェクトのプロトタイプを介して継承された値を読み取らないようにするには、プロパティがオブジェクトに属しているかどうかを確認します。

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

さらに、 ECMAScript 5Array.prototypeforEach メソッドを追加しました。これはcalbackを使用して配列を列挙するために使用できます(polyfillはドキュメントに含まれているので、古いブラウザでも使用できます)

arr.forEach(function (val, index, theArray) {
    //do stuff
});

コールバックがfalseを返してもArray.prototype.forEachは壊れないことに注意することは重要です。 jQuery および Underscore.js は短絡可能なループを提供するためにeachに独自のバリエーションを提供します。

75
zzzzBov

配列をループしたい場合は、標準の3部構成のforループを使用してください。

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

myArray.lengthをキャッシュするか、逆方向に繰り返すことで、パフォーマンスを最適化することができます。

34
Quentin

私はこれが古い投稿であることを知っています、そして、非常に多くの素晴らしい答えがすでにあります。もう少し完全を期すために、 AngularJS を使用して別のものを投入すると思いました。もちろん、これは、Angularを使用している場合にのみ適用されます。明らかに、とにかくそれを付けたいと思います。

angular.forEachは2つの引数とオプションの3番目の引数を取ります。最初の引数は反復するオブジェクト(配列)、2番目の引数は反復関数、オプションの3番目の引数はオブジェクトコンテキスト(基本的にループ内で「this」と呼ばれる)です。

角度のforEachループを使用するには、さまざまな方法があります。最も簡単でおそらく最も使用されるのは

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

ある配列から別の配列にアイテムをコピーするのに役立つ別の方法は、

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.Push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

ただし、それを行う必要はありませんが、次のことを行うだけでよく、前の例と同等です。

angular.forEach(temp, function(item) {
    temp2.Push(item);
});

組み込みのバニラ味のforループとは対照的に、angular.forEach関数を使用することの長所と短所があります。

長所

  • 読みやすい
  • 簡単な書き込み可能性
  • 使用可能な場合、angular.forEachはES5 forEachループを使用します。ここで、forEachループはmuch forループよりも遅いため、consセクションで効率を上げます。一貫性があり標準化されているのは良いことだから、私はこれをプロとして言及している。

次の2つのネストされたループを考えてみましょう。これらはまったく同じことを行います。オブジェクトの2つの配列があり、各オブジェクトには結果の配列が含まれ、それぞれが文字列(またはその他)のValueプロパティを持っているとしましょう。そして、各結果を反復処理する必要があり、それらが等しい場合は、何らかのアクションを実行するとします。

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

これは非常に単純な仮説の例ですが、2番目のアプローチを使用してループのトリプル埋め込みを記述しました。これはvery読み取りと書き込みが困難でした。

短所

  • 効率。 angular.forEachと、ネイティブforEachは、両方ともso much通常のforループよりも低速です。..about 90%低速 =。そのため、大きなデータセットの場合、ネイティブforループに固執するのが最適です。
  • サポートを中断、継続、または返却することはありません。 continueは、実際に " accident "でサポートされています。angular.forEachを続行するには、angular.forEach(array, function(item) { if (someConditionIsTrue) return; });などの関数にreturn;ステートメントを挿入します。これは、ネイティブforEachがbreakまたはcontinueをサポートしていないという事実も原因です。

他にもさまざまな長所と短所があると確信しています。必要に応じて自由に追加してください。要するに、効率性が必要な場合は、ループのニーズに合わせて、ネイティブforループだけを使用すると思います。しかし、データセットが小さく、読みやすさや書き込み可能性と引き換えにある程度の効率があれば大丈夫な場合は、その悪い男の子に必ずangular.forEachをスローします。

29
user2359695

配列を空にしても構わない場合は、

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

xyの最後の値を含み、それは配列から削除されます。 yから最初の項目を与えたり削除したりするshift()を使うこともできます。

27
gaby de wilde

forEach の実装( jsFiddle を参照):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);
27
nmoliveira

簡単な解決策は、 underscore.jsライブラリ を使用することです。これはeachのような多くの便利なツールを提供しており、利用可能であれば自動的にジョブをネイティブのforEachに委任します。

CodePenの例 それがどのように動作するかの/

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

また見なさい

24
Micka

以下のように、 jQueryforeachの実装が3つあります。

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3
24
Rajesh Paul

おそらくfor(i = 0; i < array.length; i++)ループは最良の選択ではありません。どうして?あなたがこれを持っているならば:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

メソッドはarray[0]からarray[2]に呼び出します。最初に、これは最初にあなたが持っていない変数を参照し、次にあなたが配列内に変数を持っていないだろうそして三番目にこれはコードをより太くするでしょう。ここを見て、それが私が使っているものです:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

そしてそれを関数にしたいのなら、こうすることができます。

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

あなたが破りたい場合は、もう少しロジック:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

例:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

それは戻ります:

//Hello
//World
//!!!
22

ES6以降:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

ofinに関連する奇妙なことを避けて他の言語のforループのように機能させ、letは関数内ではなくループ内でiをバインドします。

コマンドが1つしかない場合は(中括弧({})を省略することができます).

21
Zaz

これは、インデックスが0から始まる非スパースリストの反復子です。これは、document.getElementsByTagNameまたはdocument.querySelectorAllを扱うときの一般的なシナリオです。

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

使用例:

例1

var arr = [];
[1, 2, 3].each( function(a){ a.Push( this * this}, arr);
arr = [1, 4, 9]

例2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

各pタグはclass="blue"を取得します

例3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

他のすべてのpタグはclass="red">を取得します。

例4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

そして最後に、最初の20個の青いpタグが緑色に変わります。

文字列を関数として使用するときの注意:関数はコンテキスト外で作成され、変数のスコープが確実な場合にのみ使用する必要があります。そうでなければ、スコープがより直感的な関数を渡すほうがよいでしょう。

17
Tim

ネイティブ JavaScript にはfor eachループはありません。ライブラリを使用してこの機能を取得するか( Underscore.js を推奨)、単純なforループを使用できます。

for (var instance in objects) {
   ...
}

ただし、さらに単純なforループを使用する理由があるかもしれないことに注意してください(スタックオーバーフローの質問を参照してください)繰り返しはそのような悪い考えですか?

var instance;
for (var i=0; i < objects.length; i++) {
    var instance = objects[i];
    ...
}
17
joidegn

以下のように、JavaScriptで配列をループするには、 いくつかの方法 があります。

- に対して最も一般的なものです。ループのためのコードの完全なブロック

var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

while - 条件が終了するまでループします。最速のループのようです

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

do/while - 条件が満たされている間もコードブロックをループし、少なくとも1回は実行されます。

var text = ""
var i = 0;
do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>

機能的なループ - forEachmapfilter、またreduce(それらは関数をループしますが、あなたがあなたの配列で何かをする必要がある場合に使われます。

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

配列の関数型プログラミングに関するより多くの情報と例については、ブログ投稿JavaScriptの関数型プログラミング:map、filter and reduceを見てください。

16
Alireza

ECMAScript 5(Javascriptのバージョン)はArraysで動作します。

forEach - 配列内のすべての項目を繰り返し処理し、各項目に必要なことをすべて実行します。

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is the #" + (index+1) + " in musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

場合によっては、いくつかの作り付けの機能を使った配列の操作にもっと興味があります。

map - コールバック関数の結果を使って新しい配列を作成します。このメソッドは、配列の要素をフォーマットする必要があるときに使用するのに適しています。

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

reduce - 名前のとおり、現在の要素と前の実行の結果を渡して、指定された関数を呼び出すことで配列を単一の値に縮小します。

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

every - 配列内のすべての要素がコールバック関数のテストにパスした場合、trueまたはfalseを返します。

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];  
ages.every(function(elem) {  
  return elem >= 18;
});

// Output: false

filter - filterが与えられた関数にtrueを返す要素を持つ配列を返すこと以外はすべてに非常に似ています。

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

これが役に立つことを願っています。

14
Anil Kumar Arya

forEachに割り込むための作り付けの能力はありません。実行を中断するには、以下のようにArray#someを使用します。

[1,2,3].some(function(number) {
    return number === 1;
});

これは、配列順に実行されたいずれかのコールバックがtrueを返し、残りの実行を短絡するとすぐにsomeがtrueを返すためです。 オリジナルの回答some の配列プロトタイプを参照してください。

14

私はまたこれを逆のループの構成として、そしてこの構文も欲しい人のための上記の答えとして加えたいと思います。

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

長所:

これの利点:あなたはすでに別の行で宣言される必要がないように、あなたはすでに最初に参照を持っています。オブジェクト配列をループ処理するときに便利です。

短所:

これは、参照が偽の場合は必ず無効になります。偽(未定義など)です。それは利点として使用することができます。しかし、それは読むのを少し難しくします。また、ブラウザによっては、オリジナルのものより速く動作するように「最適化されていない」ことがあります。

$.mapを使ったjQueryのやり方:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];
10
DanFromGermany

あなたの考えに最も近い方法は、配列の各要素に対して実行されるclojure関数を受け入れるArray.forEach()を使うことです。

myArray.forEach(
  (item) => {
    // do something 
    console.log(item);
  }
);

もう1つの実行可能な方法は、Array.map()を使用することです。これは同じように機能しますが、各要素をmutatesし、次のように返します。

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

ES6でループを使用する destructuring および spread演算子

ES6の初心者にとっては、構造化やスプレッド演算子の使用は人間にとって読みやすい/審美的なものとして非常に有用であることが証明されています。

次の例では、 for...of ステートメントと .forEach メソッドを使用します。

例6、7および8 は、.map.filter.reduce.sort.every.someなどの任意の機能ループで使用できます。これらのメソッドの詳細については、 Array Object を参照してください。

例1: 通常のfor...ofループ - トリックはありません。

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

例2: 単語を文字に分割する

let arrFruits = ['Apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);

}

例3: keyvalueを使ったループ 

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type: 
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet Explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

例4: オブジェクトのプロパティをインラインで取得する

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

例5: 必要なものの深いオブジェクトプロパティを取得する

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

例6: Is 例3 .forEachと共に使用

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

例7: Is 例4 .forEachと共に使用

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions 
// are required to be surrounded by parenthesis
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

例8: Is 例5 .forEachと共に使用

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});

6
darklightcode

ラムダ構文は通常IE 10以下では動作しません。

私は通常使う

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});


If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters

$("#ul>li").each(function(**index,value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});
5
Murtuza Husain

あなたはforEachを呼び出すことができます。

let Array = [1,3,2];

theArray.forEach((element)=>{ 
  // use the element of the array
  console.log(element) 
}

elementは、0から配列の長さまでの各インデックスの値を持ちます。

出力:

1    
3    
2

説明:

forEachはプロトタイプクラスです。これをtheArray.prototype.forEach(...)と呼ぶこともできます。

プロトタイプ: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b

このように配列を変更することもできます。

for(let i=0;i<theArray.length;i++){
  console.log(i); //i will have the value of each index
}
4
Nouman Dilshad

もしあなたが矢印機能でオブジェクトの配列をループしたいならば:

let arr=[{name:'john',age:50},{name:'clark',age:19},{name:'mohan',age:26}];

arr.forEach((person)=>{
  console.log('i am '+person.name+' and i am '+person.age+ ' old');
})
3
subhashish negi

概要:

配列を反復処理するとき、次の目標の1つを達成したいことがよくあります。

  1. 配列を反復処理して新しい配列を作成します。

    Array.prototype.map 

  2. 配列を反復処理し、新しい配列を作成しないでください。

    Array.prototype.forEach 

    for..ofループ

JSには、これら両方の目的を達成するための多くの方法があります。ただし、他のものよりも便利なものもあります。以下に、JavaScriptで配列の反復処理を実行するために一般的に使用される方法(最も便利なimo)を見つけることができます。

新しい配列を作成しています:Map

map()Array.prototypeにある関数で、配列のすべての要素を変換して new 配列を返します。 map()は引数としてコールバック関数を取り、以下のように動作します。

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

引数としてmap()に渡したコールバックはすべての要素に対して実行されます。その後、元の配列と同じ長さの配列が返されます。この新しい配列要素では、map()への引数として渡されるコールバック関数によって変換されます。

mapforEachfor..ofループのような他のループメカニズムとの明確な違いは、 mapは新しい配列として返され、古い配列はそのまま残ります それはsplice)のように考えます。 

また、map関数のコールバックは、2番目の引数として現在の反復のインデックス番号を提供します。さらに、3番目の引数は、mapが呼び出された配列を提供します。時々これらの特性は非常に有用である場合もあります。

forEachを使用してループする

forEachは、コールバック関数を引数として取るArray.prototypeにある関数です。その後、配列内のすべての要素に対してこのコールバック関数を実行します。 map()関数とは対照的に、forEach関数は何も返しません(undefined)。例えば:

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

map関数と同じように、forEachコールバックは2番目の引数として現在の反復のインデックス番号を提供します。 3番目の引数もforEachが呼び出された配列を提供します。 

for..ofを使って要素をループする

for..ofループは、配列(または他の反復可能なオブジェクト)のすべての要素をループ処理します。これは次のように機能します。

let arr = [1, 2, 3, 4, 5];

for(let element of arr) {
  console.log(element * 2);
}

上の例で_ elementは配列要素を表し、arrはループしたい配列です。 elementという名前は恣意的なものではないので、 'el'のような他の名前、またはこれが適用可能な場合はもっと宣言的な名前を選ぶこともできます。 

for..inループとfor..ofループを混同しないでください。 for..inは配列の列挙可能なすべてのプロパティをループ処理しますが、for..ofループは配列要素をループ処理するだけです。例えば:

let arr = [1, 2, 3, 4, 5];

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}

2

巨大な配列がある場合は、効率を上げるために iterators を使用する必要があります。イテレータは特定のJavaScriptコレクションのプロパティです( MapSetStringArray など)。とはいえ、 for..ofiteratorの下にあるものを使います。

イテレータを使用すると、リスト内の項目を1つずつストリームのように使用できるため、効率が向上します。イテレータを特別なものにしているのは、それがコレクションをどのように通過するかです。他のループは、それを反復するためにコレクション全体を最初にロードする必要がありますが、イテレータはコレクション内の現在位置を知るだけで済みます。 

現在のアイテムにアクセスするには、イテレータのnextメソッドを呼び出します。次のメソッドは、現在の項目のvalueと、コレクションの最後に達したことを示すbooleanを返します。以下は、配列からイテレータを作成する例です。 

次のように values() メソッドを使用して、通常の配列をイテレータに変換します。 

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Symbol.iterator を使って、通常の配列をイテレータに変換することもできます。 

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

通常のarrayiterator に変換することもできます。 

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

_ note _ : 

  • 反復子は事実上使い尽くされます。 
  • オブジェクトはデフォルトではiterableではありません。その場合は for..in を使用してください。値ではなくキーで機能するからです。

iteration protocolhere についてもっと読むことができます。 

1
BlackBeard
var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
    console.log("Index" + index);
    console.log("Element" + item);
})
1
John

// Looping through arrays using foreach  ES6 way

var data = new Array(1,2,3,4,5);
data.forEach((val,index) => {
    console.log("index :",index); // index
	console.log("value :", val); // value
});

0
arul prince

関数をコールバックとして受け入れ、配列内に存在する各要素に対して1回実行されるforEach()API(Javascriptが提供)を使用できます。

https://fullstackgeek.blogspot.com/2019/01/arrays-in-javascript-part-2.html

0
Ayush Jain

私はpythonから来ました、そして私はこの方法をもっとはっきりと見つけました。
theArrayは配列、インスタンスは配列の要素です。

for(let instance of theArray)
{
    console.log("The instance",instance);
}

または

for( instance in theArray)
{
  console.log("The instance",instance);
}

と比較します。

theArray.forEach(function(instance) {
    console.log(instance);
});

しかし、一日の終わりには、どちらも同じことをしています。

0
Peko Chan

コードを機能的な方法で維持したい場合は、mapを使用してください。

theArray.map(instance => do_something);

このようにして、将来の操作に合わせて新しい配列を生成し、望ましくない副作用をスキップします。

0
alejoko

forEach()を使いたい場合は、 - のようになります -

theArray.forEach ( element => {
    console.log(element);
});

for()を使いたい場合は、 - のようになります -

for(let idx = 0; idx < theArray.length; idx++){
    let element = theArray[idx];
    console.log(element);
}
0
Harunur Rashid