0

ループしているいくつかの要素にイベントリスナーを追加していますが、イベント関数でインデックスを保持するためにクロージャーが必要です。

<button>solution 1</button>
<button>solution 2</button>

<script>
var buttons = document.getElementsByTagName('button');
for (var i = 0; i < 3; i++) {
    var log = (function closure(number) {
        return function () {
            console.log(number);
        };
    })(i);

    buttons[0].addEventListener("click", log);
}
for (var i = 0, len = 3; i < len; i++) {
    (function (i) {
        var log = function () {
                console.log(i);
            };
        buttons[1].addEventListener("click", log);   
    })(i);
}
</script>

http://jsfiddle.net/paptd/11/

これらのソリューションはどちらも 0、1、2 を正しく出力します (クロージャーなしで何が起こるかを確認するには、「間違って」試してください)。

それを行う正しい方法はどれですか?

4

2 に答える 2

1

これらのいずれも使用しないでください。ループ内にn 個の同一の関数を作成しています。イベント ハンドラーを返す名前付き関数にコードをリファクタリングする必要があります。

var buttons = document.getElementsByTagName('button');

function createHandler(number) {
    return function () {
        console.log(number);
    };
}

for (var i = 0; i < 3; i++) {   
    buttons[0].addEventListener("click", createHandler(i));
}

例: http://jsfiddle.net/paptd/12/

于 2013-06-05T12:54:27.420 に答える
1

最初のものは、クロージャーを定義し、そこから関数を返し、その関数をリスナーに割り当てるため機能します。

クロージャーはループの内容全体を包含し、 の値がiそこに「ロック」されることがより明確になるため、2 番目の方がより適切に見えます。

于 2013-06-05T12:52:56.287 に答える