重複の可能性:
ループ内のJavascriptクロージャ-簡単な実用例
質問を説明するのではなく、例を示します。
for (var i = 0; i < 100; i ++) {
get_node(i).onclick = function() {
do_something_very_important(i);
}
}
実行ではなく作成時にiの値を関数に代入する方法はありますか?ありがとう。
重複の可能性:
ループ内のJavascriptクロージャ-簡単な実用例
質問を説明するのではなく、例を示します。
for (var i = 0; i < 100; i ++) {
get_node(i).onclick = function() {
do_something_very_important(i);
}
}
実行ではなく作成時にiの値を関数に代入する方法はありますか?ありがとう。
はい、できますが、提供した例では機能しません。そのループでは、非常に一般的なクロージャの問題が発生します。for
クロージャで囲まれた変数は同じ単一の環境を共有するため、onclick
コールバックが呼び出されるまでに、for
ループはそのコースを実行し、i
変数は割り当てられた最後の値を指したままになります。あなたの例では、関数には各ノードdo_something_very_important()
の値が渡されますが、これは意図したものではありません。100
関数ファクトリを使用すると、さらに多くのクロージャを使用してこの問題を解決できます。
function makeClickHandler(i) {
return function() {
do_something_very_important(i);
};
}
// ...
for(var i = 0; i < 100; i++) {
get_node(i).onclick = makeClickHandler(i);
}
クロージャがどのように機能するかをよく知らない場合、これは非常に難しいトピックになる可能性があります。簡単な紹介については、次のMozillaの記事を確認することをお勧めします。
アップデート:
@adamseが他の回答で提案したように、上記の関数ファクトリをインライン化することもできます。これは実際にはより一般的なアプローチですが、実際には上記と同じです。
for(var i = 0; i < 100; i++) {
get_node(i).onclick = (function(p) {
return function () {
// we could have used i as a parameter variable as well,
// but we're using p to better illustrate what's happening
do_something_very_important(p);
}
})(i);
}
さらに別の解決策は、自己呼び出し無名関数を使用して、各反復を独自のスコープで囲むことです。
for(var i = 0; i < 100; i++) {
(function (p) {
// we now have a separate closure environment for each
// iteration of the loop
get_node(i).onclick = function() {
do_something_very_important(p);
}
})(i);
}
はい、これは動作します...
for (var i = 0; i < 100; i++) {
get_node(i).onclick = (function(i) {
return function () {
do_something_very_important(i);
}
})(i);
}