はじめに

昨日,相方 (お仕事的な意味で) に聞かれながらもすぐに答えられなかったので,復習の意味もこめてメモ.

問題

1
2
3
4
5
<div id="target">
  <div>A</div>
  <div>B</div>
  <div>C</div>
</div>

id="target"div 要素内のそれぞれの div 要素に対してクリックイベントを登録したい...そんなとき,ついつい次のように書いてしまいます.(自分と相方(お仕事的な意味で)が.)

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
var divs = document.getElementById( 'target' )
                   .getElementsByTagName( 'div' )
;
for( var i = 0; i < divs.length; i++ ) {
  divs[i].addEventListener( 'click', function() {
    alert( i );    
  } );
}
</script>

このコードを実行すると,イベント登録したどの要素 (A,B,C とそれぞれ表示されるはず) をクリックしても,

3

なアラートしか表示されません.

一解決策

こんな風にしてみました.

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript">
var divs = document.getElementById( 'target' )
                   .getElementsByTagName( 'div' )
;
for( var i = 0; i < divs.length; i++ ) {
  ( function() {
      var j = i;
      divs[i].addEventListener( 'click', function() {
      alert( j );
    } );
  } )();
}
</script>

それぞれの要素をクリックすると,

 
1
2

のようにアラートが表示されるかと.

解説

サイ本 は 4.3.1 項,最初の 2文がすべてを物語っていましたね.

C や C++、Java と異なり、JavaScript にはブロックレベルのスコープがありません。ある関数で宣言された変数は、どのブロックで宣言されたのかにかかわらず「関数全体」で有効です。

David Flanagan,村上 列 訳 『JavaScript 第5版』 オライリー・ジャパン,p.52

おわりに

ここしばらく jQuery (そういえば,1.2.6 が出てますね) を使ってばかりで意識すらしていない状況だったので,改めて勉強し直せました.

クロスブラウザ問題とか 1つのイベントリスナーを使い回すとかは,この際おいときましょう.

こちらもあわせてどうぞ

Leave a Reply

直近のつぶやきを読み込みちゅう...