-1

重複の可能性:
javascript for loop の予期しない動作

私はnode.jsでプログラミングしていますが、奇妙な参照渡しの問題によって引き起こされる小さな問題に遭遇しました。

私は次のコードを使用します:

for(j in groups){
  console.log(j, somefunction(groups[j]))
}

関数の内部では、いくつかのファンキーなことがデータで行われますが、その後、結果として次のようになります:

3 data
3 data
3 data
3 data
3 data
3 data

それ以外の

1 data
2 data
3 data
4 data
5 data
6 data

しかし、それは正しい量の結果を保持します..

4

3 に答える 3

1

引用されたコードは、リストしたことを実行しません。おそらく、質問のために単純化する何かを失ったでしょう。

ただし、このコードには、説明している効果があります。

for(j in groups){
  doSomething(function() {
    // Callback for `doSomething`
    console.log(j, somefunction(groups[j]));
  });
}

ここで、関数を呼び出すdoSomethingだけでなく、関数 (何を行うためのコールバック) も作成していることに注意してください。

これが発生する理由は、関数が作成されたときの変数のコピーではなく、作成される関数が変数 (および実行コンテキスト内の他のすべて)への永続的な参照を持っているためです。その実行コンテキストに対するクロージャーと呼ばれます。したがって、ループが実行され、一連のことを開始するための一連の呼び出しが行われ、後でコールバックが呼び出されると 3 になるため、すべて同じになります。jdoSomethingj

通常の解決策は、次のように、呼び出される前に変更されないものを閉じる関数を作成することです。

for(j in groups){
  doSomething(makeCallback(j));
}

function makeCallback(jarg) {
    return function() {
        console.log(jarg, somefunction(groups[jarg]));
    };
}

現在、jargコールバックで ではなく を使用していますjjargは への呼び出しのコンテキストの一部であるためmakeCallback、関数を作成したときと後で呼び出されるときの間で変更されません。

データを関数にバインドするもう 1 つの方法は、Function#bind(バックグラウンドで効果的にクロージャーを作成する) を使用することです。これは、V8 エンジンにあるため、NodeJS で使用できる ES5 機能です。これがどのように見えるかです:

for(j in groups){
  doSomething(function(jarg) {
    // Callback for `doSomething`
    console.log(jarg, somefunction(groups[jarg]));
  }.bind(this, j)); // <== Note the bind
}

またはそれほど混乱しない(そしておそらくより効率的に):

for(j in groups){
  doSomething(handler.bind(this, j));
}

function handler(jarg) {
  // Callback for `doSomething`
  console.log(jarg, somefunction(groups[jarg]));
}

閉鎖についての詳細:

于 2012-07-24T15:49:09.343 に答える
0

var j = 0 を使用すると見つかりました

for(i in groups){
j = i

システムはどのように機能しますが、最高のアンサーではありません

于 2012-07-24T15:37:04.353 に答える
0

このようにしてください:-

    for(グループ内の変数 j)
    {
        //あなたのコード
    }

グローバル スコープで j を割り当てているため、j は正しい値を返しません。この助けを願っています!

于 2012-07-24T16:37:16.457 に答える