2

Javascript で配列を「正しく」反復する方法については、非常に多くの混乱があります。数百の賛成票が入った投稿が少なくとも 2 つありますが、答えは非常に矛盾しています。よくわかりません。

ES5 でArray.prototype.forEach機能が追加されました。これが最終的な答えですか、それとも介入を避けるための落とし穴がまだありますか?

真の反復がある場合は、その反復を投稿してください。ES5 を使用しても問題ありません。何について話しているのかわからない場合は投稿しないでください。

4

1 に答える 1

1

簡単な答え: 不愉快な驚きを避けたいのであれば、プロトタイプの継承を含め、Javascript のオブジェクト モデルを理解する以外に方法はありません。Javascript 配列は、基本的にいくつかの追加のプロパティを持つオブジェクトであり、他の一般的な言語の配列とは非常に異なります。

Array.prototype.forEachまた、しばしば反対するようにアドバイスされjquery.eachているクリーンよりもはるかに大きな落とし穴があります。for (var k in a)この落とし穴が他の投稿で言及されているのを見たことがありません。

見て:

Array.prototype[2] = 'hi';

var a = [];
a.forEach(alert); // nothing
alert(a);  // ''

a[3] = 3;
a.forEach(alert); // 'hi', then '3'
alert(a);  // ',,hi,1'

ここで何が起こっているのですか?を実装している MDN (「互換性」の下)の仕様に準拠したアルゴリズムを参照してくださいArray.prototype.forEach

a.forEach(myCallback)よく見られるものと多かれ少なかれ同等です

for (var p = 0, len = a.length; p < len; p++) {
    if (p in a)
        myCallback(a[p], p, a);
}

これは、プロトタイプ チェーンのプロパティも同様にループすることを意味します。ただし、プロパティを満たすだけでループするため、信頼性の低い方法でのみ使用できますp < len

100% 信頼できる方法:

以下のバージョンは、列挙可能なプロパティのみを反復処理します。このObject.getOwnPropertyNames関数は、Object.keys列挙不可能なプロパティを含める代わりに使用できます。

数値、独自、順次

a.forEach(function(v, k, a) {
    if (a.hasOwnProperty[k])
        myCallback(v, k, a);
});

独自の、順次

Object.keys(a).sort(mySortFunc).forEach(function(k) {
    myCallback(a[k], k, a);
});

数値、順次

alert("Don't do it");

自分の

Object.keys(a).forEach(function(k) {
    myCallback(a[k], k, a);
});

(制約なし)

for (var k in a) {
    myCallback(a[k], k, a);
}

私は最後のものをそれほど悪い選択肢とは考えていません。これは、反復するための非常に正直で簡潔な方法です。補足として、シーケンシャルな数値反復は、少なくとも非スパース配列の場合、ほとんどの実装でパフォーマンス上の利点があることが証明されています。しかし、仕様のせいではないかもしれません。

于 2013-11-07T18:07:31.687 に答える