1. 概要
for-in構文。通常のforよりも文量が減るため、使える言語ではハッシュにも配列にも積極的に使っています。先日JavaScriptで配列を回した際にちょっと困ったことがあったので、説明してみます。
2. 問題点
HTML上のリストを動的に構築する上で、各行の行番号にオフセットをつけて表示することになりました。1000から始まって1001, 1002, 1003...といった具合に。
配列のインデックスに1000を足せばいいので、こんな感じで書いてみたわけです:
for-in.js
var list = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot','golf'];
var offset = 1000;
for(var i in list){
var code = i + offset;
console.log(code + ' : ' + list[i]);
}
// 結果
// 01000:alpha
// 11000:bravo
// 21000:charlie
// 31000:delta
// 41000:echo
// 51000:foxtlot
// 61000:golf
予想と異なる結果になりました。インデックスiが文字列だったため、 '0' + 1000
で文字列として結合されてしまったということですね。
3. 再現性
Safari, Chrome, Firefox, IE11で試しましたが、以上の全てで再現しました。
4. 対応方法
変数の結合順序を変えたり(offset+i
)、単項+を使ったり(+i
)、キャストしてしまえば(parseInt(i)
)、一応正しく動きます。
が、MDNのJavaScriptリファレンスを見てみると、配列利用時の注意事項があります。
まとめると:
- 配列のプロトタイプにプロパティが追加されていたら、それも列挙されるぞ
- インデックス順でのアクセスは保証されていないぞ
...恐ろしい。ということで、配列をfor-inすること自体が推奨されていませんでしたので、普通のforに書き直して対応しました。