62

過去および現在のほとんどのプロジェクトでは、次のような for ループを使用する傾向があります。

var elements = document.getElementsByTagName('div');
for (var i=0; i<elements.length; i++) {
    doSomething(elements[i]);
}

「reverse while」ループを使用する方が速いと聞いたことがありますが、これを確認する実際の方法はありません。

var elements = document.getElementsByTagName('div'), 
    length = elements.length;

while(length--) {
    doSomething(elements[length]);
}

JavaScript の要素や配列のループ処理に関して、ベスト プラクティスと見なされるものは何ですか?

4

14 に答える 14

61

これが私がよく使うループのいい形です。forステートメントから反復変数を作成し、長さプロパティをチェックする必要はありません。これは、NodeListを反復処理するときに特にコストがかかる可能性があります。ただし、注意が必要です。配列内の値のいずれかが「偽」である可能性がある場合は使用できません。実際には、nullを含まないオブジェクトの配列(NodeListなど)を反復処理する場合にのみ使用します。しかし、私はその糖衣構文が大好きです。

var list = [{a:1,b:2}, {a:3,b:5}, {a:8,b:2}, {a:4,b:1}, {a:0,b:8}];

for (var i=0, item; item = list[i]; i++) {
  // Look no need to do list[i] in the body of the loop
  console.log("Looping: index ", i, "item" + item);
}

これは、逆方向にループするためにも使用できることに注意してください。

var list = [{a:1,b:2}, {a:3,b:5}, {a:8,b:2}, {a:4,b:1}, {a:0,b:8}];
    
for (var i = list.length - 1, item; item = list[i]; i--) {
  console.log("Looping: index ", i, "item", item);
}

ES6アップデート

for...ofES6以降で使用可能な名前は表示されますが、インデックスは表示されません

for (const item of list) {
    console.log("Looping: index ", "Sorry!!!", "item" + item);
}
于 2011-01-06T21:57:28.350 に答える
27

場合によっては、逆の順序でループする必要があることに注意してください(ただし、i-- も使用できます)。

たとえば、誰かが新しいgetElementsByClassName関数を使用して、特定のクラスの要素をループし、このクラスを変更したいと考えていました。彼は、2 つの要素のうち 1 つだけが変更されていることを発見しました (FF3 で)。
これは、この関数がライブ NodeList を返すためであり、Dom ツリーの変更が反映されます。リストを逆順にたどることで、この問題を回避できました。

var menus = document.getElementsByClassName("style2");
for (var i = menus.length - 1; i >= 0; i--)
{
  menus[i].className = "style1";
}

インデックス進行の増加では、インデックス 1 を要求すると、FF は Dom を検査し、元の Dom の 2 番目である style2 の最初のアイテムをスキップして、3 番目の最初のアイテムを返します!

于 2008-10-01T12:23:51.197 に答える
9

私はするのが好きです:

 
var menu = document.getElementsByTagName('div');
for (var i = 0; menu[i]; i++) {
     ...
}

すべての反復で配列の長さを呼び出すことはありません。

于 2008-10-01T13:04:13.360 に答える
7

怒鳴られる危険を冒して、私はjqueryのような JavaScript ヘルパー ライブラリを取得するか、ロジックを適切なメソッドにカプセル化するプロトタイプを取得します - どちらもそれを行うための .each メソッド/イテレータを持っています - そして、どちらもそれをクロスブラウザ互換にするよう努めています

編集: この回答は 2008 年に投稿されました。今日、はるかに優れた構造が存在します。この特定のケースは、.forEach.

于 2008-10-01T11:59:52.500 に答える
6

最初の形式を使用するのがおそらく最善の方法だと思います。これは、おそらく既知の宇宙で最も一般的なループ構造であり、実際には逆ループで時間を節約できるとは思わないためです (まだインクリメント/反復ごとのデクリメントと比較)。

他の人にとって認識可能で読みやすいコードは、間違いなく良いことです。

于 2008-10-01T12:00:24.090 に答える
6

私も簡単な方法をお勧めします (KISS !-)

-- ただし、配列の長さを 2 回以上テストしないようにするなど、いくつかの最適化を見つけることができました。

var elements = document.getElementsByTagName('div');
for (var i=0, im=elements.length; im>i; i++) {
    doSomething(elements[i]);
}
于 2008-10-01T12:08:28.300 に答える
4

Andrew Hedges のテストに関する私のコメントも参照してください ...

単純な反復、導入した最適化、および配列内の要素がすべてのループでテストされる逆の do/while を比較するテストを実行しようとしました。

残念なことに、私がテストした 3 つのブラウザーの結果は大きく異なっていましたが、最適化された単純な反復がすべての中で最速でした!-)

テスト:

500,000 個の要素を持つ配列は、実際のテストの外部で作成され、反復ごとに特定の配列要素の値が明らかになります。

試運転10回。

IE6:

結果:

シンプル: 984,922,937,984,891,907,906,891,906,906

平均: 923.40 ミリ秒。

最適化: 766,766,844,797,750,750,765,765,766,766

平均: 773.50 ミリ秒。

逆 do/while: 3375,1328,1516,1344,1375,1406,1688,1344,1297,1265

平均: 1593.80 ミリ秒。(特に厄介な結果の 1 つに注意してください)

オペラ 9.52:

結果:

シンプル: 344,343,344,359,343,359,344,359,359,359

平均: 351.30 ミリ秒。

最適化: 281,297,297,297,297,281,281,297,281,281

平均: 289.00 ミリ秒

逆 do/while: 391,407,391,391,500,407,407,406,406,406

平均: 411.20 ミリ秒。

ファイアフォックス 3.0.1:

結果:

シンプル: 278,251,259,245,243,242,259,246,247,256

平均: 252.60 ミリ秒。

最適化: 267,222,223,226,223,230,221,231,224,230

平均: 229.70 ミリ秒。

逆 do/while: 414,381,389,383,388,389,381,387,400,379

平均: 389.10 ミリ秒。

于 2008-10-02T10:22:23.663 に答える
3

Juan Mendezによって提供されたループの形式は非常に便利で実用的です。少し変更したので、false、null、ゼロ、および空の文字列でも動作するようになりました。

var items = [
    true,
    false,
    null,
    0,
    ""
];

for(var i = 0, item; (item = items[i]) !== undefined; i++)
{
    console.log("Index: " + i + "; Value: " + item);
}
于 2015-01-04T07:53:26.370 に答える
2

あなたがそれを聞きたくないのはわかっていますが、この場合、ベスト プラクティスが最も読みやすいと思います。ループがここから月までカウントされない限り、パフォーマンスの向上は十分ではありません。

于 2008-10-01T12:02:11.357 に答える
0

あなたには2つの選択肢があると思います。jQuery や同様のフレームワークなどの dom 要素の場合、適切な反復方法が得られます。2 番目のアプローチは for ループです。

于 2008-10-02T10:32:20.923 に答える
0

for ループの方が読みやすいので、私は for ループを好みます。長さから 0 へのループは、0 から長さへのループよりも効率的です。そして、逆の while ループを使用することは、あなたが言ったように foor ループよりも効率的です。比較結果のページへのリンクはもうありませんが、ブラウザーによって違いが異なることを覚えています。一部のブラウザーでは、逆の while ループが 2 倍高速でした。ただし、「小さな」配列をループしている場合は違いはありません。あなたの例では、要素の長さは「小さい」

于 2008-10-01T12:12:26.697 に答える
-1

要素のセットがルート ノードの子である場合は、 TreeWalkerを使用するのが好きです。

于 2014-10-07T08:53:15.660 に答える