2

私はこれを理解しようとしています。HTML に 3 つのボタン ID (test1、test2、test3) があります。私のjQueryでは、次のようなforループにクリック機能があります。

$(document).ready(function() {
    for (var i = 0; i < 3; i++) {
        $("#test"+i).on('click', function() {
            alert("I am clicked! ("+i+")");
        });
    }  
});

今、私はそれらのそれぞれについてメッセージを警告しています.警告のすべての(i)は最後の数字「3」を与えています. test1 と同様に、test2 と test3 を押すと?

ここで説明するjsfiddleがあります。

事前に助けと感謝を願っています;-)

4

2 に答える 2

2

問題は、割り当てているハンドラーが、関数が作成された時点でのその変数のコピーではなく、変数への永続的な参照を持っていることです。それらは、変数 (およびその他のもの)に対するクロージャーです。詳細:閉鎖は複雑ではありませんii

これを解決するにはいくつかの方法があります。

  1. 要素に情報を配置して、すべての要素が1 つのハンドラーを共有できるようにすることができます。これはおそらく推奨されます。(実際には、例にはすでにその情報があります。i要素のid値から把握できますが、現実の世界では物事はより複雑であると想定しています。)

    $(document).ready(function() {
        for (var i = 0; i < 3; i++) {
            $("#test"+i).attr("data-index", i).click(clickHandler);
        }  
    
        function clickHandler() {
            alert("I am clicked! ("+this.getAttribute("data-index")+")");
            // Or:
            alert("I am clicked! ("+$(this).attr("data-index")+")");
        }
    });
    

    更新されたフィドル

    ハンドラー関数が1 つしかなく、すべての要素のクリックを処理することに注意してください。

    単一のハンドラーを使用すると、イベント デリゲーションclickを利用して、これらの個々の要素のそれぞれではなく、祖先要素にフックすることもできます。次に例を示します。

    $("selector for ancestor").on("click", "[id^=test]", ...);
    

    更新されたフィドル

  2. ビルダー関数を使用してクリック ハンドラーを作成し、変更されないもの (ビルダーに渡す引数) を閉じることができます。

    $(document).ready(function() {
        for (var i = 0; i < 3; i++) {
            $("#test"+i).on('click', buildHandler(i));
        }  
    
        function buildHandler(index) {
            return function() {
                alert("I am clicked! ("+index+")");
            };
        }
    });
    

    更新されたフィドル

于 2013-07-13T10:10:32.433 に答える