web-dev-qa-db-ja.com

配列を持つ 'for(var item in list)'がJavaScriptで悪い習慣と見なされるのはなぜですか?

単純なゼロベースの数値インデックス配列を考えます:

var list = ['Foo', 'Bar', 'Baz'];

多くの場合、誰かが次のような配列内の変数をループすることを提案すると気づきました。

for(var item in list) { ... }

...ほぼ間違いなく、それが悪い習慣であり、代替アプローチを提案している人がいます:

var count = list.length;

for(var i = 0; i < count; i++) {
    var item = list[i];
    ...
}

上記の単純なバージョンを使用せず、代わりに2番目の例を使用する理由は何ですか?

70
Tatu Ulmanen

まず、ループの順序はfor...inループに対して未定義であるため、プロパティが希望する順序で繰り返される保証はありません。

次に、for...inは、プロトタイプから継承されたものを含む、オブジェクトの列挙可能なすべてのプロパティを反復処理します。配列の場合、ページに含まれるコードまたはライブラリがArrayのプロトタイプを拡張している場合、これが影響を与える可能性があります。

Array.prototype.remove = function(val) {
    // Irrelevant implementation details
};

var a = ["a", "b", "c"];

for (var i in a) {
    console.log(i);
}

// Logs 0, 1, 2, "remove" (though not necessarily in that order)
85
Tim Down

速度?

for(..;..;..)ループはfor .. inより36倍高速であることが判明しました ここでテストしたとき

リンク礼儀これSO answer

17
Amarghosh

For/inをそのように使用すると、itemは、リスト内の実際のオブジェクトではなく、文字列値「0」、「1」、...を列挙します。したがって、最初のスニペットの「アイテム」は、iではなく、2番目のスニペットのitemに似ています。さらに、数字が予想される場所に文字列値が列挙されます。また、リストにプロパティを設定すると、array.ID = "a123"、それらも列挙されるため。

しかし、これらの欠点があるので、あなたのチームがそれが何をするかを知っているなら、私はまだ構文が非常に役立つと思います。

1
user180326

list.foo = bar;を追加して、単純なforを使用してみてください。いくつかのライブラリ(prototypeJなど)を使用せず、配列オブジェクトに新しいプロパティを追加しない場合-簡単なforステートメントを使用できます。

0
Adelf

_for ... in ..._はリストの項目を返しませんが、代わりに配列プロパティを列挙します。

その理由だけでも、それはcannotfor (i=0; i<arr.length; i++)ループの代わりとして機能します。

適切な代替は_for ... of ..._構成です。配列などの反復可能なオブジェクトの値を列挙します。詳細については、MDN Web Docsをご覧ください。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

関連する最新のブラウザーでサポートされています(Internet ExplorerはMicrosoft Edgeに置き換えられ、カウントされません)。古いブラウザをサポートしない余裕があるなら、おそらくそれが道です。先にリンクされたMDNページの最後にある便利なブラウザーサポート表を確認して、どのブラウザーバージョンが_for ... of ..._の使用を実際に許可しているかを確認できます。

0
Alice