動的にエレメントにイベントをもたせるには・・・? -> 追記あり
きれいに書くにはどうすればいいの(´・ω・`)??
こんな場合…
(とりあえずブラウザは関係ないということで目をつぶってください…
HTMLが
<div>1</div> <div>2</div> <div>3</div> <div>4</div>
のように並んでて、javascriptのonload時に
//イベントを割り当てたいエレメントとってきてー… var hoge = document.getElementsByTagName("div"); //for文で回して一つずつに割り当てる… for(var i=0; i<hoge.length; i++){ hoge[i].addEventListener( "click", function(){ alert(i); }, true ); }
ってやると
- 動作結果
- click時に出るalertは全て"4"が出る。
- 希望動作
- for文の中でイベントがセットされた時の i をalertで出したい。
ってなる…orz
引数とか必要のない関数をセットしてやるには問題ないけど、
そうもいかないときもある…(´・ω・`)
で、for文の中でevalして書いてやると一応は期待動作にはなる。
for(var i=0; i<hoge.length; i++){ eval("hoge["+i+"].addEventListener("+ "'click',"+ "function(){ alert("+i+");},"+ "true"+ ");"); }
汚い…
でも調べたところなかなか正解も見つからず。
とりあえずこれで動いているのおkとしていますorz
きれいな書き方は一体どういうものなんでしょうか???
教えてエライ人゚・(ノД`)ノ・゚・
~~~追記~~~
今日買った本を読み進めていたらちょうど解決しました(´・ω・`)
どうやらキチンと関数のことを理解していないことが原因でしたorz
内部関数は外側の変数にアクセスしてる = コピーにアクセスしてるわけじゃない
というわけで、以下のように書けば希望動作になりました。
for(var i=0; i<hoge.length; i++){ hoge[i].addEventListener( "click", function(_i){ return function(){ alert(_i); }; }(i), true ); }
無名関数を定義して、i を渡して、即実行。 で、イベントハンドラ関数が無名関数に渡されたパラムを処理。 これで i != _i になるんですね。
すっきりした!!