Javascriptテクニック-for in文で配列を巡回しないでください


一、なぜfor in文を使わないのか
jqModalというjqueryプラグインは多くの人が使用したことがあると推定されています.jqModalソースコードの内部には、hsという関数があり、ネストされたループがあります.
 

  
for ( var i in {jqmShow: 1 ,jqmHide: 1 })
for(var s in this [i])
if (H[ this [i][s]])
H[
this [i][s]].w[i]( this );
return F;
}

 
最初のfor in遍歴のターゲットは匿名のオブジェクトで、問題ありません.
2番目のfor inは、コンテキストに基づいてthis[i]が配列オブジェクト(Array)であることを確認します.
多くのJSの先駆者は,性能のほかに予想外のバグが発生する可能性があるため,配列オブジェクトにfor in文を用いないように警告している.先人の言うことを聞かないで、損をして目の前でほほほ.
今日のはjqModalを例に、このようなバグがいつ現れるかを説明し、戒めとしています.
二、問題の再現
キーワード:原生Array類、拡張Array類
for in文が配列オブジェクトを遍歴する潜在的なバグは、オリジナルArrayクラスが他のjsスクリプトライブラリによってプロトタイプ拡張された場合(例えば、1つのtoJSONメソッドであるArray.prototype.toJSON=xxxxを追加するなど)、forinで拡張されたArrayオブジェクトを遍歴する論理がオリジナルArrayオブジェクトを遍歴する論理と異なることである.
簡単な例を挙げると
 

  
var x = [ 1 ];

for ( var s in x){

  alert(s);

};

通常、Arrayが元のjsクラスである場合、上記の文はalertメソッドを1回だけ実行し、sは配列のインデックス0である必要があります.ただし、Arrayクラスが拡張されてtoJSONメソッドが1つ増えた場合、上記の文はalertを2回実行し、1回目はsがインデックス0、2回目はsがメソッド名'toJSON'となる.
 
もしあなたが設計したコードのロジックがオリジナルArrayクラスを基準にしているならば、ある日あなたの同僚がページの中で第三者のJSライブラリを引用して、このライブラリはまたちょうどArrayクラスを拡張して、結果は想像しにくくて、元のコードロジックがもう成立しない可能性が高いです.
 
このような原生JS類を拡張するライブラリについて、有名なのはprototypeです.jsは、ArrayクラスにtoJSON、eachなど多くの方法を拡張しています.私は今、jqueryの創始者がprototypeに火をつけた理由を知っています(多くの人が特殊な理由で1つのページでjqueryと同時にprototypeを使うと、予想外の衝突問題が多く、1つのnoConflictだけでは解決できません).また、jqModalの著者が私のこの文章を読めば、prototypeを恨むことに対しても、「for inで配列を巡るのは賢明ではないが、もっと死ぬべきはprototypeだ」と言うだろう.
 
上記のように、jqModalを使用している場合、他の理由でprototypeを使用している場合は、おめでとうございます.衝突により、jqModalのバウンドがie 6、ie 7の下でcloseClass設定のボタンで自動的に閉じることができなくなります.デバッグコードを追跡すると、本明細書の冒頭で述べたhsメソッドのfor inループに異常があることがわかります.の
三、問題を解決する
配列の場所を巡り、for inの代わりにfor var文を使用します.
 
回転元:http://www.cnblogs.com/mamboer/archive/2010/10/19/no-for-in-on-array.html