Javascript ループ内のイベント ハンドラー - クロージャーが必要ですか? 質問する

Javascript ループ内のイベント ハンドラー - クロージャーが必要ですか? 質問する

私は他の人から引き継いだ HTML と Javascript のコードを使って作業しています。このページは 10 秒ごとにデータ テーブルを (非同期リクエスト経由で) 再読み込みし、DOM コードを使用してテーブルを再構築します。問題のコードは次のようになります。

var blah = xmlres.getElementsByTagName('blah');
for(var i = 0; i < blah.length; i++) {
    var td = document.createElement('td');
    var select = document.createElement('select');
    select.setAttribute("...", "...");
    select.onchange = function() {
        onStatusChanged(select, callid, anotherid);
    };
    td.appendChild(select);
}

onchangeただし、要素に対してイベントが発生すると、テーブル内のすべてのメソッド<select>に同じ値が渡されるように見えます(ループの各反復でこれを検証し、新しい個別の値が与えられています)。onStatusChanged()<select>callidanotherid

これは、構文を使用してイベント ハンドラーを設定する方法の性質が原因で発生していると思われますselect.onchange = function()。これが正しく機能している理由を理解している場合、この構文は、onchange イベントのクロージャを、これら 2 つの参照を参照する関数に設定し、ループの最後の反復で設定された最終値を持つことになります。イベントが発生すると、およびによって参照される値は、callid最後anotheridの反復で設定された値であり、個々の反復で設定された値ではありません。

渡すパラメータの値をコピーする方法はありますかonStatusChanged()?

質問と受け入れられた回答をよりよく反映するためにタイトルを変更しました。

ベストアンサー1

確かに、ここでクロージャを実装する必要があります。これはすべき動作します(テストしていないので教えてください)

var blah = xmlres.getElementsByTagName('blah');
for(var i = 0; i < blah.length; i++) {
    var td = document.createElement('td');
    var select = document.createElement('select');
    select.setAttribute("...", "...");
    select.onchange = function(s,c,a)
    {
        return function()
        {
            onStatusChanged(s,c,a);
        }
    }(select, callid, anotherid);
    td.appendChild(select);
}

おすすめ記事