変数スコープに関する初歩的なミスで詰んでた

なんか書いてるjsのコードでの問題が切り離せたので備忘録に。

    var array = [];
    
    for(var i=0; i < 3; i++){
      console.log("i=", i);
      array.push(function(){
        console.log("in function ", i);
      });
      array[i]()
    }

    console.log(array.length);
    for(var j=0; j < array.length; j++){
      console.log("run function no.", j);
      array[j]();
    }

こういうコードで、最後の配列に入った関数を実行するときに、

run function no. 0
in function 0
run function no. 1
in function 1
run function no. 2
in function 2

となることを期待していたというのが本質のバグ作ってた。このコードの最後は実際は、

run function no. 0
in function 3
run function no. 1
in function 3
run function no. 2
in function 3

と実行される。「なんで"i<3"なのにi=3になってるんだよ!」という類のことで悩んでいたのだが、カウンタが生きているならば、forが終ったあとはその制約の一個次になるんだったなあと高校のBASICの授業を思いだす。

DIM I

FOR I = 0 TO 3
  PRINT I
NEXT
PRINT I

みたいに書くと(正確な文法忘れた)

0
1
2
3
4

となるはず

追記

"JavaScript: The Good Parts"のクロージャの章に全く同じの載ってました。結局こう直します。

    var array = [];

    for(var i=0; i < 3; i++){
      array.push(function(j){
        return function(){
          console.log("in function (revised): ", j);
        };
      }(i));
    }

    for(var j=0; j < array.length; j++){
      console.log("run function no.", j);
      array[j]();
    }