連想配列 - javascript 配列 抽出




For each?JavaScriptの配列全体に? (19)

後方へのループ

私はreverse forループがここで言及に値すると思います:

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

利点:

  • 一時的なlen変数を宣言する必要はありません。 array.length 、各繰り返しでarray.lengthと比較する必要はありません。
  • 逆順でDOMから兄弟削除するほうが効率的です。 (ブラウザは内部配列の要素の移動を少なくする必要があります)。
  • ループ中、またはインデックスiの後で配列変更した場合(たとえば、 array[i]でアイテムを削除または挿入する場合)、フォワードループは、左にシフトしたアイテムをスキップして、 iを再処理します右にシフトされた項目。 伝統的なforループでは、処理1を必要とする次の項目を指すようにiを更新することができます 、反復の方向を反転するだけで、しばしば簡単洗練されたソリューションになります。
  • 同様に、 ネストされた DOM要素を変更または削除する場合 、逆の処理はエラー回避できます。 たとえば、子ノードを処理する前に、親ノードのinnerHTMLを変更することを検討してください。 子ノードに到達するまでに、親ノードのinnerHTMLが書き込まれたときに新しく作成された子に置き換えられてDOMから切り離されます。
  • 利用可能な他のオプションのいくつかよりも、入力と読み込み短くなっています。 それはforEach()とES6のfor ... ofに失わfor ... of

欠点:

  • アイテムを逆順に処理します。 結果から新しい配列を作成したり、画面上に物を印刷したりしていた場合は 、元の順序に対して出力が当然逆になります
  • 順序を保持するために兄弟を最初の子としてDOMに繰り返し挿入することは効率が悪いです。 DOMノードを効率的に、順番に作成するには、通常どおりループを進めて追加するだけです(また、「ドキュメントフラグメント」も使用します)。
  • 逆のループは、ジュニア開発者に混乱招いています。 (あなたの見通しに応じて、あなたは優位性を考慮するかもしれません。)

私はいつもそれを使うべきですか?

いくつかの開発者は、フォワードをループする正当な理由がない限り、デフォルトでreverse forループを使用します

パフォーマンスの向上は通常わずかですが、それは悲鳴のようなものです。

「リスト内のすべてのアイテムにこれを行うだけで、私はそのオーダーを気にしない!」

しかし実際には実際には意図の信頼できる指標ではありません 。なぜなら、あなた注文を気にかけているときと区別がつかず、本当に逆にループする必要があるからです。 実際、ECMAScriptを含む多くの言語では現在利用できないが、 forEachUnordered()などのようにforEachUnordered()ことができる「ドントケア」という意図を正確に表現するには、別の構造が必要になります。

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

forEach()を使う方が良いです

一般に、 明快さと安全性がより重視される上位レベルのコードでは、デフォルトのパターンとしてArray::forEachを使用することをお勧めします。

  • 読むのは明らかです。
  • これは、ブロック内でシフトされないことを示します(これは、長いwhileループとwhileループでは常に驚いている可能性がwhileます)。
  • それはクロージャのための自由な範囲を与えます。
  • ローカル変数の漏れや、外部変数との偶発的な衝突(および突然変異)を減らします。

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

(意図の議論があなたにとって意味をなさない場合、あなたとあなたのコードは、 プログラミングスタイルとあなたの脳についてのCrockfordの講義を見て恩恵を受けるかもしれません。)

どのように機能するのですか?

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

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

あなたはi--が中間節(私たちは通常比較を参照)であり、最後の節は空である(私たちは通常i++を見ている)ことに気付くでしょう。 つまり、 i--は継続の条件としても使われます。 重要なのは、各反復の前に実行され、チェックされます。

  • どのように爆発することなくarray.lengthから始めることができますか?

    i--は各反復の前に実行するので、最初の反復では、 array.length - 1 -out-of-bounds undefined項目に関する問題を回避するarray.length - 1項目に実際にアクセスします。

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

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

    このトリックは、 - iとは異なり、後続のi--演算子はiデクリメントしますが、減算のに値をi--ます。 あなたのコンソールはこれを実証することができます:

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

    [5, 5, 4]

    だから最終的な反復では、 は以前は1でi i--式は0に変更されましたが、実際には1 (真理値)となり、条件が満たされます。 次の反復では、 i-1-1に変更しますが、 0 (偽)を生成しますこれにより、実行がすぐにループの最下部から脱落します。

    伝統的なForward forループでは、 i++++iは交換可能です(Douglas Crockfordが指摘するように)。 しかし、reverse forループでは、デクリメントも条件式であるため、インデックス0のアイテムを処理したい場合は、私はスティックにする必要があります。

トリビア

一部の人々 forループの逆に小さな矢印を描き、ウインクで終了します。

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

クレジットはWYLに行き、reverse forループの利点と恐怖を私に見せてくれます。

JavaScriptを使用して配列内のすべてのエントリをループするにはどうすればよいですか?

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

forEach(instance in theArray)

theArrayは私の配列ですが、これは間違っているようです。


概要:

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

  1. 配列全体を繰り返し処理し、新しい配列を作成したい:

    Array.prototype.map

  2. 配列全体を繰り返し処理し、新しい配列を作成しないようにします。

    Array.prototype.forEach

    for..of ループ

JSでは、これらの両方の目的を達成する多くの方法があります。しかし、あるものは他のものより慣習的です。以下では、javascriptで配列の繰り返しを行うためによく使われるいくつかのメソッド(最もconventientなもの)を見つけることができます。

新しい配列の作成: Map

map()Array.prototype配列のすべての要素を変換して新しい配列を返す関数です。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()

間に明確な違いmapなど、他のループメカニズムforEachfor..ofループは、あるmap新しい配列として戻り、そのまま古い配列を去る(のように考えていると、あなたが明示的にそれを操作する場合を除きますsplice)。

また、map関数のコールバックは、現在の反復のインデックス番号を第2引数として提供することにも注意してください。さらに、第3引数は、map呼び出された配列を提供します。これらのプロパティは非常に便利な場合もあります。

ループを使用して forEach

forEach上に配置されている機能でありArray.prototype、引数としてコールバック関数をとります。次に、配列内のすべての要素に対してこのコールバック関数を実行します。map()関数とは対照的に、forEach関数はnothing(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..offor..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);
}


for each実装( 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
  }
);

ES6のでループを使用したdestructuringおよび拡散オペレータ

ES6のデストラクタリングと使い方は、ES6の人が読めるようにするためには非常に便利ですが、javascriptの退役軍人の中には、それが面倒だと思うかもしれませんが、後輩や他の人が役に立つかもしれません。

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

実施例6,7及び8は、のような任意の機能ループで使用することができ.map.filter.reduce.sort.every.someチェックアウトこれらの方法の詳細については、配列オブジェクトを

例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:でループkeyし、value

// 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:です例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:です例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:です例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);
});


TL; DR

  • 保障措置と一緒に使用for-inない限り、または少なくともそれがあなたを噛む可能性があることを少なくとも意識している場合を除きfor-inを使用for-inないでください。
  • あなたのベストベットは通常です

    • for-ofループ(ES2015 +のみ)、
    • Array#forEachspec | MDN )(またはその親族など)(ES5 +のみ)
    • 単純な昔ながらのforループ、
    • 保護措置を講じている。

しかし、もっと多くの探求し、読むことがあります...

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

私はすぐに、ES2015オプションをES5エンジンにも使用でき、ES2015をES5に移行することができます。 "ES2015 transpiling" / "ES6 transpiling"をさらに検索する

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

実際の配列の場合

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

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

詳細:

1. forEachと関連するものを使用する

forEachspec | MDN )を使用すると、ES5で追加されたArrayフィーチャーに(直接またはポリフィルを使用して)追加された漠然と現代的な環境(IE8ではなく)でも使用できます。

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

forEachはコールバック関数を受け取り、オプションでそのコールバックを呼び出すときにthis値を使用します(上記では使用されていません)。 コールバックは配列内の各エントリに対して順番に呼び出され、疎配列内に存在しないエントリをスキップします。 上記の引数を1つだけ使用したにもかかわらず、コールバックは3つの要素で呼び出されます。各エントリの値、そのエントリのインデックス、および反復処理する配列への参照(関数がまだ便利でない場合)。

IE8のような古くなったブラウザ(2016年9月の時点でNetAppの市場シェアが4%を上回っています)をサポートしていない限り、 forEachはshimのない汎用ウェブページでうまく使用できます。 時代遅れのブラウザをサポートする必要があるならば、シミング/ポリ充てんforEachは簡単に実行できます(いくつかのオプションで "es5 shim"を検索します)。

forEachは、反復関数の引数として指定されているスコープ内のインデックス変数と値変数を宣言する必要がないというメリットがあります。

各配列エントリの関数呼び出しを実行する際のランタイムコストが心配されている場合は、そうでないようにしてください。 blog.niftysnippets.org/2012/02/foreach-and-runtime-cost.html

さらに、 forEachは「すべてを通るループ」機能ですが、ES5では、以下を含むいくつかの他の便利な「配列と操作を行う」機能を定義しています。

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

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

時には古い方法が最高です:

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

配列の長さがループ中に変更されず、パフォーマンスが重視されるコード(おそらく)にある場合、長さを上げる少し複雑なバージョンが少し速くなるかもしれません:

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); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "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 => {
        alert("Index is: " + index);
    });
}

5つのdivがある場合は、最初にクリックした場合は「Index is:0」を、最後をクリックした場合は「Index is:4」を取得します。 これは、 let代わりにvarを使うとうまくいきませ

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

あなたは、 for-inを使用するように指示する人々を得るでしょうが、それはfor-in のためのものfor-inはありませんfor-inループは、配列のインデックスではなく、 オブジェクトの列挙可能なプロパティを使用します注文は保証されておらず、ES2015(ES6) では保証されません。 ES2015では、 [[OwnPropertyKeys]][[Enumerate]] 、およびそれらをObject.getOwnPropertyKeysように使用するものを使用して、オブジェクトのプロパティの順序を定義しますが、 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 are explained
        /^0$|^[1-9]\d*$/.test(key) &&    // and then hidden
        key <= 4294967294                // away below
        ) {
        console.log(a[key]);
    }
}

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

  1. オブジェクトはその名前で独自のプロパティを持ちます(プロトタイプから継承したものではありません)。

  2. キーは、通常の文字列形式のベース10の数値文字列で、値は<= 2 ^ 32 - 2(4,294,967,294)です。 その番号はどこから来たのですか? これは、仕様の配列インデックスの定義の一部です。 他の数(非整数、負の数、2 ^ 32 - 2より大きい数)は配列インデックスではありません。 2 ^ 32 - 2の理由は、最大のインデックス値を2 ^ 32 - 1よりも低くします。これは配列のlengthが持つことができる最大値です。 (例えば、配列の長さは32ビットの符号なし整数に収まります) 私のブログ記事のコメント RobGは、以前のテストが正しくないと指摘しています)。

ほとんどの配列でループ反復ごとにオーバーヘッドが少し増えますが、配列が疎な場合は、実際に存在するエントリだけがループするため、より効率的にループすることができます。 例えば、上記の配列では、キー"0""10""10000"合計3回ループします.10,001回ではありません。

さて、あなたは毎回それを書きたくないので、これをあなたのツールキットに入れるかもしれません:

function arrayHasOwnIndex(array, prop) {
    return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}

そして、私たちはこれを次のように使います:

for (key in a) {
    if (arrayHasOwnIndex(a, key)) {
        console.log(a[key]);
    }
}

あるいは、「ほとんどのケースで十分」というテストに興味があるなら、これを使うことができますが、それが近いうちにそれは間違いありません。

for (key in a) {
    // "Good enough" for most cases
    if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
        console.log(a[key]);
    }
}

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

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

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

出力:

a
b
c

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

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

場合によっては、イテレータを明示的に使用することもできます。 あなたもそれを行うことができますが、それはfor-ofよりもはるかに厄介for-of 。 これは次のようになります。

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

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

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

  • values() :これは私が上記で使用したものです。 イテレータを返します。ここで、各valueはその反復の配列エントリです(前述の例では"b""b""c" )。
  • keys() :それぞれのvalueがその反復のキーであるイテレータを返します(したがってa上記では"0" 、次に"1""2" )。
  • entries() :反復子を返します。ここで、各valueはその反復の[key, value]という形式の配列です。

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

実際の配列とは別に、 lengthプロパティと数値名のプロパティ( NodeListインスタンス、 argumentsオブジェクトなど)を持つ配列のようなオブジェクトもあります。どのように内容をループしますか?

配列に対して上記のいずれかのオプションを使用する

上の配列アプローチの少なくともいくつか、場合によっては大部分またはすべてが、配列のようなオブジェクトによくよく適用されます。

  1. それぞれのおよび関連する(ES5 +)

    Array.prototypeのさまざまな関数は "意図的に汎用"であり、通常、関数Array.prototype関数Array.prototypeを介して配列のようなオブジェクトで使用できFunction#apply 。 (この答えの最後にホスト提供のオブジェクトの警告がありますが、これはまれな問題です。)

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

    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はオブジェクトが提供するイテレータを使用します(存在する場合)。 さまざまな配列のようなオブジェクト、特にホストから提供されるオブジェクトで、これがどのように機能するかを見なければなりません。 たとえば、 querySelectorAllNodeListの仕様が反復をサポートするように更新されました。 getElementsByTagNameHTMLCollectionの仕様がHTMLCollectionません。

  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 +、しかし簡単にpolyfilled)は、配列のようなオブジェクトから配列を作成します。 そう:

    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関数をホスト提供の配列のようなオブジェクト(JavaScriptリストではなくブラウザで提供されるDOMリストなど)とともに使用する場合は、ターゲット環境でテストして、ホスト提供のオブジェクトは適切に動作します。 ほとんどが適切に動作していますが、テストすることが重要です。 その理由は、あなたが使いたいArray.prototypeメソッドのほとんどが、ホスト提供のオブジェクトに依存して抽象的な[[HasProperty]]操作に正直な答えを与えるからです。 この記事を書いている時点では、ブラウザは非常にうまく動作しますが、5.1仕様では、ホスト提供のオブジェクトが正当でない可能性があります。 これは§8.6.2 、そのセクションの冒頭の大きなテーブルの下にいくつかの段落があります)。

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

(私はES2015仕様で同等の言葉遣いを見つけることができませんでしたが、それでも結構です。)この記事の執筆時点では、現代のブラウザ[ NodeListインスタンスなど]の共通のホスト提供の配列のようなオブジェクトはdo [[HasProperty]]正しく処理しますが、テストすることが重要です。


編集 :この答えは絶望的に時代遅れです。 より現代的なアプローチについては、配列で利用可能なメソッドを見てください。 関心のある方法は次のとおりです。

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

JavaScriptで配列を反復処理する標準的な方法は、-loopのバニラfor

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

ただし、この方法は、配列が密で、各インデックスが要素で占められている場合にのみ有効です。 配列がまばらな場合は、配列に実際に存在しない多くのインデックスを繰り返し処理するため、この方法でパフォーマンスの問題に遭遇する可能性があります。 この場合、for..in -loopは良いアイデアかもしれません。 ただしfor..inもレガシーブラウザでも列挙されるので、配列の目的のプロパティ(つまり配列要素)のみが有効になるように適切な保護手段を使用する必要があります。プロパティはenumerable定義されています。

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


これは、インデックスが0から始まるNON-sparseリストのイテレータです。これは、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タグが緑色に変わります

文字列を関数として使用する場合の注意:関数はコンテキスト外で作成され、可変スコープの特定の場所でのみ使用する必要があります。それ以外の場合は、スコープがより直感的な関数を渡す方が良い。


また、これを逆ループの構成として追加し、この構文も好きな人のための上記の答えを追加したいと思います。

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

長所:

これには次のような利点があります。最初のような参照が既にあり、後で別の行で宣言する必要はありません。オブジェクト配列をループするときに便利です。

短所:

これは、参照がfalse - false(未定義など)のときはいつでも破棄されます。しかしそれは利点として使用することができます。しかし、読むのが少し難しくなります。また、ブラウザによっては、元のものよりも速く動作するように最適化されていない場合もあります。


一部の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 5では、 Array.prototypeを使用して配列を列挙するために使用できるArray.prototypeメソッドが追加されました(polyfillはドキュメントにあり、古いブラウザでも使用できます)。

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

コールバックがfalse返すときにArray.prototype.forEachがブレークしないことに注意することが重要です。 jQueryUnderscore.jsはそれぞれのバリエーションを提供し、短絡するループを提供します。


私はこれが古い投稿であることを知っています、そして既に多くの素晴らしい答えがあります。 もう少し完全にするために、私は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);
});

現在angular.forEach、組み込みのバニラ風味のforループとは対照的に、この機能を使用する賛否両論があります。

長所

  • 簡単な読みやすさ
  • 簡単な書き込み可能性
  • 使用可能な場合angular.forEachは、ES5 forEachループを使用します。For Eachループは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のアプローチを使用してループ用に3重埋め込みを作成しましたが、それを読むのは非常に難しく、そのことについては書きました。

短所

  • 効率。angular.forEach、およびネイティブはforEach、そのことについては、両方ともそんなに通常より遅くforループ....およそ90%遅く。大規模なデータセットの場合は、ネイティブforループに固執するのがベストです。
  • 中断しない、続ける、またはサポートを返す continue実際には " accident " によってサポートされていangular.forEachますが、あなたが単純にそのreturn;ようなangular.forEach(array, function(item) { if (someConditionIsTrue) return; });関数の中にその繰り返しの関数から出て行くようなステートメントを置くことで続行します。これは、ネイティブforEachがブレークをサポートしていないか、どちらかを続行していないことも原因です。

他にも様々な長所と短所があると確信しています。あなたが合っているものを自由に追加してください。私は、効率性が必要な場合forは、ループを必要とするネイティブループだけに固執しています。しかし、あなたのデータセットが小さく、読みやすさと書き込み可能性と引き換えにいくつかの効率があきらめても大丈夫ならば、是非angular.forEach、その悪い少年に投げてください。


配列をループしたい場合は、標準の3パートforループを使用forます。

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

myArray.lengthをキャッシュmyArray.lengthか、それを逆方向に反復することで、パフォーマンスの最適化を行うことができます。


配列を空にしても構いません:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

xyの最後の値を含み、配列から削除されます。 shift()を使って、最初の項目をyから取り出して削除することもできます。


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

CodePenの動作例は次のとおりです。

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

も参照してください

  • Array::forEach
  • for_each...in(MDN)、その説明するfor each (variable in object)ECMA-357(の一部として廃止されEAX)標準。
  • for...of(MDN)for (variable of object)は、Harmony(ECMAScript 6)提案の一部として使用する次の反復方法について説明します。

for eachネイティブJavaScriptループがありません。ライブラリを使用してこの機能を利用することができます(私はUnderscore.jsを推奨forします)。単純なループを使用してください。

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

しかし、さらに簡単に使用することの理由があるかもしれないことに注意してくださいfor(スタックオーバーフローの問題参照ループを、このような悪い考え反復配列と「のために...で」使用しているのはなぜか?

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

あなたが使用したい場合forEach()、それはのようになります -

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

あなたが使用したい場合for()、それはのようになります -

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


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

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]

そこに侵入する能力はありませんforEach。実行を中断するには、Array#some以下のようにします:

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

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


以下のように、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、reduceを参照してください


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




iteration