ラムダ式の遅延実行
Javascirpt で 思ったとおり実行されないと質問された。
こんなやつ
ボタン button0〜button9 の onclick イベント をクロージャでまとめて定義したいらしいんだけれど、
for (var i = 0; i <= 9; i++) {これ、実行するとどのボタンも 10 を表示しますよね。
$get("button" + i).onclick = function() { alert(i); };
}
LINQ でいつ実行されるかを考えるというエントリを何度かしたけれど同じことですね。
Javascript もクロージャは遅延実行されます。
// i の値は 0参照している i の値はボタンクリック時には 10 になっているので、どのボタンを押しても 10 が表示されるわけですね。
for (var i = 0; i <= 9; i++) {
$get("button" + i).onclick = function() { alert(i); };
}
// i の値は 10
これは C# 2.0 の匿名メソッドや C#3, VB9 の ラムダ式 でも同じことがいえます。
VB.NET このようなコードを記述した場合次の警告が表示されます。
For i = 0 To 4警告
lambdaList.Add(Function() j)
Next
For Each lambda In lambdaList
Console.Write(lambda.Invoke().ToString() & " ")
Next
ラムダ式で繰り返し変数を使用すると、予期しない結果が発生する可能性があります。代わりに、ループ内にローカル変数を作成して、繰り返し変数の値を割り当ててください。
結果
5 5 5 5 5
ループ内にローカル変数を作れとあるので、
For i = 0 To 5結果
Dim j = i
lambdaList.Add(Function() j)
Next
For Each lambda In lambdaList
Console.Write(lambda.Invoke().ToString() & " ")
Next
0 1 2 3 4
ただ、Javascript の場合は 変数のスコープがメソッドの先頭で作られてしまうので結局できず...ボタンにプロパティを作って持たせればできるけれど、これでいいの??