button
要素の束を生成し、DOM機能を介してbody
のdiv
に追加するコードがあります。の機能(イベントハンドラ)をonclick
イベントのそれぞれbutton
に動的に設定します。ルーピングとクロージャ
0
から20
までを繰り返すことによって実行されます。
問題は、私はイベントハンドラでループカウンタi
を使用したいと思いますが、最終的な値ではなくループの反復で値が得られます。i
が得られます。最初は、私は閉鎖によってこれを行うことができると思ったが、その後私はそれが当初考えていた方法を実行しなかったことに気づいた。 i
は各反復を変更し続け、他のすべてのanon関数(クロージャを介して)は、範囲内のi
がすべて同じ値を指しているという点で同じi
を参照する必要があります。 onclick
をトリガーすると、すべて同じ値を報告するためです。
だから、私はそれを修正するにはどうしたらいいですか?私はi
を別の変数に設定しようとしましたが、そのような新しい変数はちょうどi
というようにそれぞれの反復を更新しているので、同じ結果になります。私はここに簡単なものがないと思う。
<!DOCTYPE html>
<html>
<head>
<title>loop closure test</title>
<script language="javascript" type="text/javascript">
window.onload = function() {
var div = document.getElementById("myDiv");
for(var i = 0; i <= 20; i++) {
var b = document.createElement("button");
b.setAttribute("type","button");
b.appendChild(document.createTextNode("Button" + i.toString()));
b.onclick = function(event) {
var date = new Date(2012, 3, i);
alert(date.getMonth() + "/" + date.getDate() + "/" + date.getFullYear());
}
div.appendChild(document.createElement("br"));
div.appendChild(b);
}
}
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
私はそれについてもう少し考えてみました。基本的に私はi
を別のクロージャの中に閉じ込める必要がありました。私はこのルートで行くことにしました:
<!DOCTYPE html>
<html>
<head>
<title>loop closure test</title>
<script language="javascript" type="text/javascript">
window.onload = function() {
var div = document.getElementById("myDiv");
for(var i = 0; i <= 20; i++) {
div.appendChild((function() {
var day = i;
var b = document.createElement("button");
b.setAttribute("type","button");
b.appendChild(document.createTextNode("Button" + i.toString()));
b.onclick = function(event) {
var date = new Date(2012, 3, day);
alert(date.getMonth() + "/" + date.getDate() + "/" + date.getFullYear());
}
return b;
}()));
div.appendChild(document.createElement("br"));
}
}
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
[JavaScriptでのループのためにクリックハンドラを割り当て]の可能な重複(http://stackoverflow.com/questions/8881306/assign-click-in-for-in-loop-in-javascript) – Pointy
はい、各ループのクロージャで動作します。 – Bergi
重要なことは、JavaScriptのローカル変数が関数レベルでスコープされていることです。したがって、各ハンドラに独自の "i"を与えたい場合は、* another *関数でハンドラ関数をインスタンス化する必要があります。 StackOverflowには、この問題に関する質問がたくさんあります。 – Pointy