8

jsfiddle を参照してください: http://jsfiddle.net/LsNCa/2/

function MyFunc() {

    for (var i = 0; i < 2; i++) { // i= 0, 1
        var myDiv = $('<div>');
        
        myDiv.click(function(e) {
            alert(i);    // both the two divs alert "2", not 0 and 1 as I expected
        });
        $('body').append(myDiv);
    }
}

var myFunc = new MyFunc();

divをクリックすると、それぞれ「0」と「1」をアラートするようにしたいのですが、どちらも「2」をアラートします。

div をクリックしてイベントがトリガーされると、ハンドラーは変数の値をどこでどのように見つけますiか?

クロージャーを追加すると目標が達成されることを認識しています。しかし、なぜ?

4

4 に答える 4

7
    function MyFunc() {

    for (var i = 0; i < 2; i++) { // i= 0, 1
        (function(j) {
            var myDiv = $('<div>');

            myDiv.click(function(e) {
                alert(j);
            });
            $('body').append(myDiv);
        })(i);
    }
}

var myFunc = new MyFunc();

上記のコードは、正しく動作させる方法です。クロージャがなければ、常に i の最後の値になります。私たちがしていることは、 i をクロージャーに投稿し、ランタイムにその瞬間の値を「記憶」させることです。

于 2013-07-16T07:46:29.153 に答える
2

すべてのイベント ハンドラー関数が同じ variable を参照しているため、クロージャーが必要ですi。ループはこれforを更新し、ループが完了すると、変数には が含まれます2。次に、誰かが DIV の 1 つをクリックすると、その変数にアクセスします。

iこれを解決するには、各イベント ハンドラーを、クロージャーが作成された時点の値のスナップショットを含む独自の変数を持つクロージャーにする必要があります。

于 2013-07-16T07:42:00.410 に答える
1

この記事を読むことをお勧めします

JavaScript は宣言を巻き上げます。これは、var ステートメントと関数宣言の両方が、それらを囲むスコープの先頭に移動されることを意味します。

上記の回答で @Barmar が述べたように、変数iは両方のイベント ハンドラによって参照されています。

ループ内で関数を宣言することは避けてください。以下に、必要なことを行うコードをいくつか示します。

jQueryを使用していると思います。

function MyFunc() {

    for (var i = 0; i < 2; i++) { // i= 0, 1
        var myDiv = $('<div>');

        $('body').append(myDiv);
    }
    $('div').on('click', function() {
        alert($(this).index());
    });
}

var myFunc = new MyFunc();
于 2013-07-16T07:51:47.203 に答える
0

「alert()」呼び出しは、for ループが完了した後に発生します。つまり、「i」の値は、その後のすべての最後の値になります。「i」の個々の値をキャプチャするには、新しい関数を作成して各値のクロージャーを作成する必要があります。

function MyFunc() {

    function alertFn(val) {
        return function () {
            alert(val);
        };
    }

    for (var i = 0; i < 2; i++) {
        var myDiv = $('<div>');
        myDiv.click(alertFn(i));
        $('body').append(myDiv);
    }
}

var myFunc = new MyFunc();

クロージャーは、関数に渡された時点で "i" の値を取得し、alert() が期待する値を表示できるようにします。

于 2013-07-16T07:53:11.717 に答える