プロが教える店舗&オフィスのセキュリティ対策術

複数のボタンがあり、それぞれがクリックされると、
対応したdiv要素がanimateを行う、というギミックを作成しております。

配列に複数のボタンのid名と、各div要素のid名を格納しておき、
for文でclickイベントを登録しようとしましたが、うまく動作しませんでした。

【例1】
jQuery(function($){
 var buttonArray = ["#button0", "#button1", "#button2"];
 var divArray = ["#box0", "#box1", "#box2"];

 for(i=0; i<buttonArray.length; i++){
  $(buttonArray[i]).click(function(){
   $(divArray[i]).animate({width: "0px"}, "slow", "swing");
  });
 }
});

---------------------------------------------------
以下のように書くと、正常に動作しました。

【例2】
jQuery(function($){
 var buttonArray = ["#button0", "#button1", "#button2"];
 var divArray = ["#box0", "#box1", "#box2"];

 $(buttonArray[0]).click(function(){
  $(divArray[0]).animate({width: "0px"}, "slow", "swing");
 });
 $(buttonArray[1]).click(function(){
  $(divArray[1]).animate({width: "0px"}, "slow", "swing");
 });
 $(buttonArray[2]).click(function(){
  $(divArray[2]).animate({width: "0px"}, "slow", "swing");
 });
});

---------------------------------------------------
そこで質問なのですが、

・for文ではイベントの登録は行えないのか?
・今回のようなケースの場合、どのように書くのが適切か?

上記2点に関して、ご回答、ご意見を頂けますと幸いです。
どうぞよろしくお願い申し上げます。

A 回答 (1件)

JavaScriptの言語仕様の問題です。


forループが終わってイベント登録が完了した時点では、変数iは3になっています。
その後、ユーザー操作でマウスのクリック動作した時に、イベント関数が呼び出されますから、
> $(divArray[i]).animate({width: "0px"}, "slow", "swing");
この部分は、全て
> $(divArray[3]).animate({width: "0px"}, "slow", "swing");
として処理されることになります。
そのため、期待通りの動作にならないのです。

対策ですが、
---
jQuery(function($){
 var buttonArray = ["#button0", "#button1", "#button2"];
 var divArray = ["#box0", "#box1", "#box2"];
 function setCallback(i) {
  $(buttonArray[i]).click(function(){
   $(divArray[i])).animate({width: "0px"}, "slow", "swing");
  });
 }
 for(i=0; i<buttonArray.length; i++){
  setCallback(i);
 }
});
---
のように、イベント設定処理を関数化すれば、ループ中で関数呼び出しにより毎回新たな変数iが作られますから、期待通りの結果になるかと思います。

さらに、無名関数を使えば、
---
jQuery(function($){
 var buttonArray = ["#button0", "#button1", "#button2"];
 var divArray = ["#box0", "#box1", "#box2"];
 for(i=0; i<buttonArray.length; i++){
  (function(i) {
   $(buttonArray[i]).click(function(){
    $(divArray[i])).animate({width: "0px"}, "slow", "swing");
   })(i);
 }
});
---
のように書くこともでき、もうちょっと簡潔になります。
    • good
    • 0
この回答へのお礼

mtaka2様、ご回答ありがとうございます。

 >>JavaScriptの言語仕様の問題です。
 >>forループが終わってイベント登録が完了した時点では、変数iは3になっています。
 >>その後、ユーザー操作でマウスのクリック動作した時に、イベント関数が呼び出されますから

なるほど…!
forループ毎にイベント登録され、それを呼び出してくれるのではなく、
clickイベント時にループ完了時点の変数iで呼び出されるのですね。
非常によく理解することができました。

また、対策の具体例を2つも提示して頂き、大変助かります。
どちらも試したところ、期待する動作を得ることができました。

jQueryの無名関数は、あらゆる場面で万能ですね…。
引き続き勉強していきたいと思います。

本当にありがとうございました!

お礼日時:2012/03/03 03:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!