JavaScriptのfor文がややこしい。

ややこしいので忘れたときのためにメモ。主に配列を走査するとき。

for inで配列の走査してはダメ

Array.prototype.hoge = function() {};

for (var i in ['a', 'b', 'c']) {
    console.log(i); // 0, 1, 2, hoge が表示される
}

for in はオブジェクトのプロパティを走査する記法だから、プロトタイプが拡張された場合に対応出来ない。
forまたは後述のforEachで書くべし。

forEachでできるけど...

breakは使えなくて、continueはreturnとなる。
古いプラウザでは動かないらしいのでそれも注意。

['a', 'b', 'c'].forEach(function(i) {
    console.log(i); // a, b, cが表示される 
});

配列の走査でbreakを使いたいときは

普通にforで書くか、someを使うか、each(jQuery)を使うとかする。

someを使う

valueとindexを返すので、Pythonのenumerate的な使い方もできる。
ただし、Pythonのenumerateではindex, valueの順だけどsomeでは逆となる。

[1,2,3,4,5].some(function(v,i){
  console.log(v,i);
  return v > 2; // 2より大きいvに当たればbreak
});

/* 1 0
   2 1
   3 2 が表示される */

each(jQuery)を使う

trueがcontinueに、falseはbreakになる。

var arr = [1, 2, 3, 4, 5]

$.each(arr, function() {
    if (this < 3) {
        console.log(this);
        return true; // continue
        
    } else {
        return false; // break
    }
});

//1, 2が表示される。

eachは連想配列でも使える。連想配列Pythonで言うdict。

var dict = {one: 1, two: 2, three: 3, four: 4, five: 5}

$.each(dict, function(i, v) {
    if (v < 3) {
        console.log(i, v);
        return true; // continue
        
    } else {
        return false; // break
    }
});

/* one 1
   two 2 が表示される */

連想配列はfor in使ってOK

var dict = {hoge: 'hoge', fuga: 'fuga'}

for (var i in dict) {
  console.log(dict[i]); // hoge, fugaが表示される。
}

多重forループにはラベルを使う

ラベルを使うと、breakとかcontinueが楽になる。

L: for(var i = 0; i < 3; i++){
    for(var j = 0; j < 3; j++){
        console.log(i, j);
        if(i == 1 && j == 1)
            break L;
    }
}

/* 0 0
   0 1
   0 2
   1 0
   1 1 と表示される */