解決済み

【jQuery】for文ではイベント登録できない?

  • 困ってます
  • 質問No.7338986
  • 閲覧数4096
  • ありがとう数5
  • 気になる数0
  • 回答数1
  • コメント数0

お礼率 100% (1/1)

複数のボタンがあり、それぞれがクリックされると、
対応した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点に関して、ご回答、ご意見を頂けますと幸いです。
どうぞよろしくお願い申し上げます。

質問者が選んだベストアンサー

  • 回答No.1

ベストアンサー率 73% (867/1179)

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);
 }
});
---
のように書くこともでき、もうちょっと簡潔になります。
お礼コメント
icle

お礼率 100% (1/1)

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

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

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

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

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

本当にありがとうございました!
投稿日時 - 2012-03-03 03:53:11
感謝経済、優待交換9月20日スタート
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集


より良い社会へ。感謝経済プロジェクト始動

ピックアップ

ページ先頭へ