1

重複の可能性:
ループ内のJavascriptクロージャ-簡単な実用例

質問を説明するのではなく、例を示します。

for (var i = 0; i < 100; i ++) {
  get_node(i).onclick = function() {
    do_something_very_important(i);
  }
}

実行ではなく作成時にiの値を関数に代入する方法はありますか?ありがとう。

4

2 に答える 2

1

はい、できますが、提供した例では機能しません。そのループでは、非常に一般的なクロージャの問題が発生します。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);
}
于 2010-09-05T17:07:32.060 に答える
0

はい、これは動作します...

for (var i = 0; i < 100; i++) {
  get_node(i).onclick = (function(i) {
    return function () {
      do_something_very_important(i);
    }
  })(i);
}
于 2010-09-05T17:11:10.010 に答える