よく言われていることですが、JavaScriptでfor in
ループを使うときは注意が必要です。
for in
は、ただの for
と違い、オブジェクトのプロパティがループの対象になるためです。
特に配列だと危険性が増します。
// 例えばこんな配列があって、、
var arr1 = ['a1', 'a2', 'a3'];
var arr2 = ['b1', 'b2', 'b3'];
var arr3 = ['c1', 'c2', 'c3'];
// さらに1つの配列に格納されていて、、
var arr = [arr1, arr2, arr3];
// すべての配列のひとつ目を取得したい
for (i in arr) {
console.log(arr[i].shift()); // "a1" "b1" "c1"
}
ここでfor in
の前でarr
に関数を追加した場合、エラーが発生します。
arr.myFunc = function () {
return 0;
}
for (i in arr) {
console.log(arr[i].shift()); // "a1" "b1" "c1" "TypeError: arr[i].shift is not a function..."
}
これはprototype
に対しての追加でも同様です。
Array.prototype.myFunc = function () {
return 0;
}
for (i in arr) {
console.log(arr[i].shift()); // "a1" "b1" "c1" "TypeError: arr[i].shift is not a function..."
}
どうなっているかというと、インデックスにmyFunc
がはいってきます。
for (i in arr) {
console.log(i); // "0" "1" "2" "myFunc"
}
素直にfor
ループで書くほうが安全です。
// 配列の length は 3
console.log(arr.length); // 3
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].shift()); // "a1" "b1" "c1"
}
だれがどこで配列を拡張するかわかったもんじゃないです、はい。