2011-12-26 16 views
5

私はforループをjavascriptで実行しています。このループでは、リストアイテムを作成してクリックイベントをバインドします。このリストアイテムをクリックすると、現在のループオブジェクトのデータをパラメータとして関数を呼び出すことができます。バインドされたクリックイベントのJavascriptループは常に最終結果を返します

問題は、どのリスト項目をクリックしても問題ではありません。パラメータとして渡されるデータは、クリックされている現在のループではなく、ループしているオブジェクトの最後の要素です。

for(e in data) { 

    var suggestItem = $('<li>'+ data[e]['name'] +'</li>'); 

    suggestItem.click(function() { 
     $(this).addClass('activeSuggestion'); 
     suggestSelect(suggestField, data[e]);  
    }); 

    suggestList.append(suggestItem); 

} 

私はこれがなぜ起こるのか分かりませんが、どうすればそれを処理すべきか分かります。

+1

ループ内で作成された[jQueryイベントハンドラ]の複製が可能です(http://stackoverflow.com/questions/7774636/jquery-event-handler-created-in-loop) – Pointy

答えて

3

eを閉鎖する必要があります。

jQueryを使用しているので、最も簡単な方法は、eの現在の値をjQueryのdata関数で保存することです。 JavaScriptのすべての関数パラメータは値渡しであるため、これはクロージャを効果的に中断します。クリックハンドラは、ハンドラが作成されたときの値がeのもので動作し、ループが終了すると値eが保持されません。

for(e in data) { 

    var suggestItem = $('<li>'+ data[e]['name'] +'</li>'); 

    suggestItem.data('savedE', e).click(function() { 
     $(this).addClass('activeSuggestion'); 
     suggestSelect(suggestField, data[$(this).data('savedE')]); 
    }); 

    suggestList.append(suggestItem); 

} 
+0

これはそのトリックでした。ありがとう –

+0

@JustinCarlson - 私の喜び - 幸運! –

5

これは古典的なJavascriptクロージャの質問です。 clickイベントがトリガされると(何かをクリックすると)、ループはすでに実行を終了しています。 eの値は、dataの最後のキーが何であれです。問題の解決策は、ループ内に新しいスコープを作成することです。

for(var e in data) { 
    (function(datum) { 
     suggestList.append(
      $('<li>' + datum.name + '</li>') 
      .click(function() { 
       $(this).addClass('activeSuggestion'); 
       suggestSelect(suggestField, datum);  
      }); 
     ); 
    })(data[e]); 
} 

Javascriptは関数スコープであるため、新しい関数が見つかるたびに新しいスコープが作成されます。上記のコードは、data[e]の値をdatumにトラップします。これは、それを関数のパラメータとして渡すためです。それほど混乱する可能性がある、それをコードする別の方法:

for(var e in data) { 
    (function() { 
     var datum = data[e]; 
     suggestList.append(
      $('<li>' + datum.name + '</li>') 
      .click(function() { 
       $(this).addClass('activeSuggestion'); 
       suggestSelect(suggestField, datum);  
      }); 
     ); 
    })(); 
} 

これは、関数にパラメータを渡していませんが、JavaScriptが関数スコープですので、クリックイベントがトリガされるたびに、それがどこdatumを探します割り当てられた。

eがグローバル変数になるのを防ぐfor(VAR e in data)にも注意してください。

関連する問題