かるあ のメモ

アクセスカウンタ

help リーダーに追加 RSS ラムダ式の遅延実行

<<   作成日時 : 2007/10/16 20:58   >>

トラックバック 1 / コメント 2

Javascirpt で 思ったとおり実行されないと質問された。
こんなやつ

ボタン button0〜button9 の onclick イベント をクロージャでまとめて定義したいらしいんだけれど、
for (var i = 0; i <= 9; i++) {
  $get("button" + i).onclick = function() { alert(i); };
}

これ、実行するとどのボタンも 10 を表示しますよね。
LINQ でいつ実行されるかを考えるというエントリを何度かしたけれど同じことですね。
Javascript もクロージャは遅延実行されます。
// i の値は  0
for (var i = 0; i <= 9; i++) {
  $get("button" + i).onclick = function() { alert(i); };
}
// i の値は 10

参照している i の値はボタンクリック時には 10 になっているので、どのボタンを押しても 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 の場合は 変数のスコープがメソッドの先頭で作られてしまうので結局できず...ボタンにプロパティを作って持たせればできるけれど、これでいいの??

# 2007/10/26
die さんの指摘で javascript の評価式を修正

設定テーマ

注目テーマ 一覧

月別リンク

トラックバック(1件)

タイトル (本文) ブログ名/日時
式を実行して式を作る。
以前のこの記事 に die さんからコメントをいただきました。 ラムダ式の遅延実行 ...続きを見る
かるあ のメモ
2007/10/26 14:48

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(2件)

内 容 ニックネーム/日時
おひさしぶりです。ここのRSSを登録してたリーダーのサービスが消えちゃって、しばらく取得できてませんでした。この件、すでに解決済みかもしれませんけど、こんなのでどうでしょうか:

for (var i = 0; i <= 9; i++) {
$get("button" + i).onclick = (function(i) {
return function() {alert(i);};
})(i);
}

(ちなみに本文中のJavaScriptの例、「i < 9」になってるけどOK?)
die
2007/10/26 12:49
お久しぶりです。

> (function(i) { return function() {alert(i);};
直に評価してオブジェクトを作って返すわけですね。なるほどー。
カリー化ってやつですか?
#間違っている気がする(汗

対象がボタンオブジェクトだったので、確かこんな風にしてました。
var elem = $get("button" + i);
elem.args = i;
elem.onclick = function() { alert(this.args); };

die さんのやつのが良いですね。

>(ちなみに本文中のJavaScriptの例、「i < 9」になってるけどOK?)
あっあふれてる。w
ご指摘ありが問うございます。
かるあ
2007/10/26 13:33

コメントする help

ニックネーム
本 文