jQueryでの配列と連想配列の扱いでハマった

まず結論から、配列と連想配列は分けるべきということがわかりました。悔しくて冗長に書きましたが、それだけですorz

jQueryには、$.each という配列を走査するforeach的な関数があります。他の言語でもあるように配列と連想配列を考えなくてもいいと思いこんで、以下のようにしていました。

var array = []; // ここで配列を代入
array["hoge"] = "fuga";
$.each( array, function(i){
    alert(i);
}
// -> 何も表示されません

array["hoge"]を走査してくれることを期待していたのですが、反応なし。jQueryのソースを見てみると、jQueryは、lengthプロパティの有無で配列と連想配列を区別していることがわかります。

// $.eachのソース部分から引用
if ( object.length == undefined ) {
    for ( var name in object )
        if ( callback.call( object[ name ], name, object[ name ] ) === false )
            break;
} else
    for ( var i = 0, length = object.length, value = object[0]; 
        i < length && callback.call( value, i, value ) !== false;
        value = object[++i]
    ){}
}

そこで、素直に配列を連想配列にします。

var array = {}; // ここで連想配列を代入
array["hoge"] = "fuga";
$.each( array, function(i){
    alert(i);
});
// -> hoge とアラート表示されます

これで意図するような動作になりました。

感想

わかってしまえば当然なのですが、気づくまでに時間かかりました(実はソース読んだのも後付けで、適当にいじっていたらわかったという・・・。オブジェクトやら__proto__やらprototypeやら、javascriptはまだよくわかっていないので、そこらへんも調べたい。