forループ中のラムダ式におけるクロージャ化け
forループ中でラムダ式(または無名関数)を使う場合は少し注意が必要
クロージャにループ中に更新される値(hoge[i]とか)を使用すると、実行されたタイミングでの値になってしまう
だいたいの場合、ループ終了時の値(最後の要素とか)
だいたいの場合、期待しているのはラムダ式を定義したタイミングでの値
こう言うことが起きる
code:js
let n;
for(let i=0; i<3;i++){ // let
if(i==0) n = ()=>{console.log(i); };
}
n(); // => 0
let n;
for(var i=0; i<3;i++){ // var
if(i==0) n = ()=>{console.log(i); };
}
n(); // => 3
解決法としては、ループ内でブロックスコープな変数を新たに用意する
code:js
let n;
for(var i=0; i < 3; i++){
let i = i;
if(i==0) n=()=>{console.log(_i); };
}
n(); // => 0
for(let i=0; i < 3; i++)でも良い。勝手にlet i=i;をしてくれる
code:cs
System.Action n = null;
for(var i=0; i < 3; i++){
var _i = i;
if(i==0) n = ()=>System.Console.WriteLine(_i);
}
n(); // => 0
jsと違って、var i=iをすると変数名重複でエラーになる