JavaScriptを使用して配列内のすべてのエントリをループする方法を教えてください。
私はそれがこのようなものだと思った:
forEach(instance in theArray)
theArray
は私の配列ですが、これは正しくないようです。
TL; DR
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 "):
forEach
および関連(ES5 +)を使用しますfor
ループを使用するfor-in
を正しく使用するfor-of
を使用します(暗黙的にイテレーターを使用します)(ES2015 +)詳細:
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
(コールバックを繰り返し呼び出して値を作成し、以前の値を渡します。詳細については仕様を参照してください。配列の内容や他の多くの内容を合計するのに便利です)reduceRight
(reduce
と同様ですが、昇順ではなく降順で動作します)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動作します。
for-in
を正しく使用するfor-in
を使用するように言われますが、 for-in
の目的ではありません 。 for-in
は、配列のインデックスではなく、オブジェクトの列挙可能なプロパティをループします。 順序は保証されていません、ES2015(ES6)でも保証されていません。 ES2015 +は、オブジェクトプロパティの順序を定義します( [[OwnPropertyKeys]]
、および [[Enumerate]]
、およびそれらを使用するものは Object.getOwnPropertyKeys
)が、それはしないfor-in
がその順序に従うことを定義します。 (詳細は この他の回答 で。)
配列上のfor-in
の唯一の実際の使用例は次のとおりです。
最初の例を見てください:適切な保護手段を使用している場合は、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つのチェックに注意してください。
オブジェクトの名前がownプロパティ(プロトタイプから継承したものではない)を持つこと、および
キーがすべて10進数である(例:科学表記法ではなく、通常の文字列形式)
数値に強制されたときのキーの値は<= 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);
});
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
とは異なり、エントリがアクセスされる順序はインデックスの番号順です。
場合によっては、反復子を明示的に使用することもできます。それもできますが、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
があります。 (done
はfalse
の場合はオプション、value
はundefined
の場合はオプションです。)
value
の意味は、イテレーターによって異なります。配列は、反復子を返す(少なくとも)3つの関数をサポートします。
values()
:これは上で使用したものです。それぞれのvalue
がその反復の配列エントリであるイテレータを返します(前の例の"a"
、"b"
、および"c"
)。keys()
:各value
がその反復のキーであるイテレータを返します(上記のa
の場合、それは"0"
、"1"
、"2"
になります)。entries()
:各value
がその反復の[key, value]
形式の配列であるイテレーターを返します。真の配列の他に、length
プロパティと数値名を持つプロパティ(NodeList
インスタンス、arguments
オブジェクトなど)を持つarray-likeオブジェクトもあります。それらのコンテンツをどのようにループしますか?
上記の配列アプローチの少なくともいくつか、そしておそらくほとんどまたはすべてさえも、配列のようなオブジェクトに頻繁に等しく適用されます。
forEach
および関連する(ES5 +)を使用します
Array.prototype
のさまざまな関数は「意図的に汎用」であり、通常は Function#call
または Function#apply
を介して配列のようなオブジェクトで使用できます。 (この回答の最後にあるホスト提供オブジェクトに関するCaveatを参照してください。ただし、これはまれな問題です。)
forEach
のNode
プロパティで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`
});
単純なfor
ループを使用する
明らかに、単純なfor
ループが配列のようなオブジェクトに適用されます。
for-in
を使用する正しく使用する
for-in
は、配列と同じセーフガードを使用して、配列のようなオブジェクトでも機能するはずです。上記の#1のホスト提供オブジェクトの警告が適用される場合があります。
for-of
を使用(暗黙的にイテレータを使用)(ES2015 +)
for-of
は、オブジェクトが提供するイテレーターを使用します(存在する場合)。さまざまな配列のようなオブジェクト、特にホストが提供するオブジェクトでこれがどのように動作するかを確認する必要があります。たとえば、NodeList
からのquerySelectorAll
の仕様は、反復をサポートするために更新されました。 HTMLCollection
からのgetElementsByTagName
の仕様はそうではありませんでした。
イテレータを明示的に使用する(ES2015 +)
#4を参照してください、イテレータがどのように動作するかを確認する必要があります。
また、配列のようなオブジェクトを真の配列に変換したい場合もあります。それは驚くほど簡単です:
slice
配列のメソッドを使用する
配列のslice
メソッドを使用できます。これは、上記の他のメソッドと同様に「意図的に汎用」であるため、次のように配列のようなオブジェクトで使用できます。
var trueArray = Array.prototype.slice.call(arrayLikeObject);
したがって、たとえば、NodeList
を真の配列に変換する場合は、次のようにします。
var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
以下のホスト提供オブジェクトの警告を参照してください。特に、これはIE8以前では失敗することに注意してください。ホスト提供のオブジェクトをthis
として使用することはできません。
スプレッド構文(...
)を使用
この機能をサポートするJavaScriptエンジンでES2015の スプレッド構文 を使用することもできます。
var trueArray = [...iterableObject];
したがって、たとえばNodeList
を真の配列に変換したい場合、スプレッド構文を使用すると、これは非常に簡潔になります。
var divs = [...document.querySelectorAll("div")];
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]]
を正しく処理しますが、テストすることが重要です。)
編集 :この答えは絶望的に古くなっています。より現代的なアプローチについては、 配列で利用可能なメソッド をご覧ください。興味のある方法は次のとおりです。
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は簡単で、コードを読みやすくするため、含めることをお勧めします。
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].
}
ここで、reverseforループに言及する価値があると思います。
for (var i = array.length; i--; ) {
// process array[i]
}
len
変数を宣言したり、各反復でarray.length
と比較したりする必要はありません。どちらもわずかな最適化です。array[i]
で項目を削除または挿入する)、前方ループはスキップします位置iに左に移動したアイテム、または右に移動したi番目のアイテムを再処理します。従来のforループでは、couldupdateiを処理する必要がある次のアイテムを指すように更新します-1、ただし反復の方向を単に逆にする多くの場合、シンプルおよび よりエレガントなソリューション 。forEach()
とES6のfor ... of
を失いますが。一部の開発者は、順方向にループする正当な理由がない限り、デフォルトで逆forループを使用します。
パフォーマンスの向上は通常は取るに足らないものですが、それは一種の悲鳴です。
「リスト内のすべてのアイテムにこれを行うだけで、順序は気にしません!」
ただし、実際にはnotは意図の信頼できる指示です。なぜなら、doを気にするときと区別できないためです。順序、そして実際にneedを逆にループします。そのため、実際には、「ドントケア」の意図を正確に表現するために別の構造が必要になります。これは、ECMAScriptを含むほとんどの言語では現在利用できないものですが、たとえばforEachUnordered()
と呼ぶことができます。
順序が重要ではなく、効率が懸念事項である場合(ゲームまたはアニメーションエンジンの最も内側のループで)、go-toパターンとしてreverse forループを使用することは許容される場合があります。既存のコードで逆forループが表示されることを覚えておいてください必ずしも意味するわけではありません順序は無関係です!
一般的に、clarity and safetyがより重要な上位レベルのコードの場合、デフォルトパターンとして Array::forEach
を使用することをお勧めします。
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に送られます。
いくつかの _ 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
に forEach
メソッドを追加しました。これはcalbackを使用して配列を列挙するために使用できます(polyfillはドキュメントに含まれているので、古いブラウザでも使用できます)
arr.forEach(function (val, index, theArray) {
//do stuff
});
コールバックがfalse
を返してもArray.prototype.forEach
は壊れないことに注意することは重要です。 jQuery および Underscore.js は短絡可能なループを提供するためにeach
に独自のバリエーションを提供します。
配列をループしたい場合は、標準の3部構成のfor
ループを使用してください。
for (var i = 0; i < myArray.length; i++) {
var arrayItem = myArray[i];
}
myArray.length
をキャッシュするか、逆方向に繰り返すことで、パフォーマンスを最適化することができます。
私はこれが古い投稿であることを知っています、そして、非常に多くの素晴らしい答えがすでにあります。もう少し完全を期すために、 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
をスローします。
配列を空にしても構わない場合は、
var x;
while(x = y.pop()){
alert(x); //do something
}
x
はy
の最後の値を含み、それは配列から削除されます。 y
から最初の項目を与えたり削除したりするshift()
を使うこともできます。
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
}
);
簡単な解決策は、 underscore.jsライブラリ を使用することです。これはeach
のような多くの便利なツールを提供しており、利用可能であれば自動的にジョブをネイティブのforEach
に委任します。
CodePenの例 それがどのように動作するかの/
var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});
Array.prototype.forEach()
のドキュメント 。for each (variable in object)
はECMA-357( _ eax _ )規格の一部として推奨されていないと説明されています。for (variable of object)
を使用して反復する次の方法を説明しています。以下のように、 jQuery にforeach
の実装が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
おそらく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
//!!!
ES6以降:
list = [0, 1, 2, 3]
for (let obj of list) {
console.log(obj)
}
of
はin
に関連する奇妙なことを避けて他の言語のfor
ループのように機能させ、let
は関数内ではなくループ内でi
をバインドします。
コマンドが1つしかない場合は(中括弧({}
)を省略することができます).
これは、インデックスが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タグが緑色に変わります。
文字列を関数として使用するときの注意:関数はコンテキスト外で作成され、変数のスコープが確実な場合にのみ使用する必要があります。そうでなければ、スコープがより直感的な関数を渡すほうがよいでしょう。
ネイティブ 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];
...
}
以下のように、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>
機能的なループ - forEach
、map
、filter
、また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を見てください。
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]
これが役に立つことを願っています。
私はまたこれを逆のループの構成として、そしてこの構文も欲しい人のための上記の答えとして加えたいと思います。
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];
あなたの考えに最も近い方法は、配列の各要素に対して実行される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: 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: 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);
});
ラムダ構文は通常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);
});
あなたは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
}
もしあなたが矢印機能でオブジェクトの配列をループしたいならば:
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');
})
配列を反復処理するとき、次の目標の1つを達成したいことがよくあります。
配列を反復処理して新しい配列を作成します。
Array.prototype.map
配列を反復処理し、新しい配列を作成しないでください。
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()
への引数として渡されるコールバック関数によって変換されます。
map
とforEach
やfor..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);
}
巨大な配列がある場合は、効率を上げるために iterators
を使用する必要があります。イテレータは特定のJavaScriptコレクションのプロパティです( Map
、 Set
、 String
、 Array
など)。とはいえ、 for..of
はiterator
の下にあるものを使います。
イテレータを使用すると、リスト内の項目を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());
通常のarray
を iterator
に変換することもできます。
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 protocol
here についてもっと読むことができます。
var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
console.log("Index" + index);
console.log("Element" + item);
})
// 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
});
関数をコールバックとして受け入れ、配列内に存在する各要素に対して1回実行されるforEach()API(Javascriptが提供)を使用できます。
https://fullstackgeek.blogspot.com/2019/01/arrays-in-javascript-part-2.html
私は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);
});
しかし、一日の終わりには、どちらも同じことをしています。
コードを機能的な方法で維持したい場合は、mapを使用してください。
theArray.map(instance => do_something);
このようにして、将来の操作に合わせて新しい配列を生成し、望ましくない副作用をスキップします。
forEach()
を使いたい場合は、 - のようになります -
theArray.forEach ( element => {
console.log(element);
});
for()
を使いたい場合は、 - のようになります -
for(let idx = 0; idx < theArray.length; idx++){
let element = theArray[idx];
console.log(element);
}