引数束縛
0pt
複数の要素にイベントハンドラを追加したい場合、forで回したりするけど、関数オブジェクトをそのまま渡すとうまくいかない。
これは、関数の呼び出しがイベント追加時ではなく実行時に行われる(遅延評価)からである。下記の例では、event.addで追加した無名関数が参照してる変数iは、forループを終えた後(つまりi=10の時)のiである。
無名関数はイベントごとに別オブジェクトなんだけど、中身のiはみんな同じものを読んでいる。
event = { events: [], add: function(event){ this.events.push(event); }, run: function(){ for (var i = 0; i < this.events.length; i++){ (this.events[i])(); } } }; for (var i = 0; i < 10; i++){ event.add(function(){ print(i + " " ); }); } event.run(); // 10 10 10 10 10 10 10 10 10 10 10
なので、無名関数が別々のiを参照してやればいい。
どうするか。別々のiを返すような関数を作成する。
下記の例では、一番上の方の無名関数は、引数iを与えるとそのiをprintするような関数を返す。
for (var i = 0; i < 10; i++){ event.add(function(v){ return function(){ print(v + "\n"); } }(i)); } event.run(); // 0 1 2 3 4 5 6 7 8 9
カリー化は複数の引数をとる関数を変形して、1つの引数でその処理を行う関数を返す関数にすることで、ちょっと意味が違うみたい。カリー化が、この引数束縛の概念を利用しているのかな。
コメントはまだありません