簡単な答え: 不愉快な驚きを避けたいのであれば、プロトタイプの継承を含め、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);
}
私は最後のものをそれほど悪い選択肢とは考えていません。これは、反復するための非常に正直で簡潔な方法です。補足として、シーケンシャルな数値反復は、少なくとも非スパース配列の場合、ほとんどの実装でパフォーマンス上の利点があることが証明されています。しかし、仕様のせいではないかもしれません。