4

タイトルについて申し訳ありません-私はそれを表現する方法を理解できませんでした。

シナリオは次のとおりです。

要素を構築する関数があります:

buildSelect(id,cbFunc,...)

buildSelect内では、次のことを行います。

select.attachEvent('onchange',cbFunc);

次のような配列もあります。

var xs = ['x1','x2','x3'...];

これらすべてを考えると、これを行うコードがいくつかあります。

for(var i = 0; i < xs.length; i++)
{
    buildSelect(blah,function(){ CallBack(xs[i],...) },...);
}

問題は、これらの選択の1つでonchangeが起動されると、CallBack()に正しく移動しますが、最初のパラメーターが正しくないことです。たとえば、3番目の選択を変更すると、CallBack()がxs [2]で呼び出されることを期待します。代わりに、xs[3]などのさまざまなものを取得します。

これに少し変更すると:

for(var i = 0; i < xs.length; i++)
{
    var xm = xs[i];
    buildSelect(blah,function(){ CallBack(xm,...) },...);
}

CallBack()でまだ間違った値を取得しています。これはスコープ/クロージャーに関連しているとのことですが、何がわからないようです。

最初の選択で、最初のパラメーターをxs [0]として、2番目の選択でxs [1]を使用して、onchangeのCallBackを呼び出すようにします。ここで何が間違っているのでしょうか?

xsがグローバル変数であることを明確にする必要があります。

ありがとう

4

4 に答える 4

4

xm独自のスコープでその値を閉じることにより、その値をキャプチャする必要があります。

これを行うには、別の関数呼び出しが必要です。

buildCallback( curr_xm ) {

      // this function will refer to the `xm` member passed in
    return function(){ CallBack(curr_xm,...) },...);
}

for(var i = 0; i < xs.length; i++)
{
    var xm = xs[ i ];
    buildSelect(blah,buildCallback( xm ),...);
}

これxmで、コールバックが参照するのは、に渡したものbuildCallbackです。

保持する必要がある他の用途がiある場合は、代わりにそれを送信できます。

buildCallback( curr_i ) {


      // this function will refer to the `i` value passed in
    return function(){ CallBack( xs[ curr_i ],...) },...);
}

for(var i = 0; i < xs.length; i++)
{
    buildSelect(blah,buildCallback( i ),...);
}
于 2011-02-17T03:57:22.313 に答える
4

はい、閉鎖が役立つと思います:

for(var i = 0, l = xs.length; i < l; i++)
{
    buildSelect(
        blah,
        function(xm){
            return function(){
                CallBack(xm,...)
            };
        }(xs[i]),
        ...
    );
}

編集: forループも少し最適化しました。

編集:説明を追加します。あなたがしているのは、1つの引数(xm)をとる無名関数を作成し、すぐに関数を呼び出すことです(括弧の直後に)。この無名関数は、buildSelect()の引数として元の関数も返す必要があります。

于 2011-02-17T03:58:28.833 に答える
4

問題は確かにスコープに関連しています-JavaScriptには関数スコープのみがあり、ブロックスコープやループスコープはありません。i変数とのインスタンスは1つだけでありxm、これらの変数の値はループが進むにつれて変化します。ループが完了すると、最後に保持された値のみが残ります。匿名関数は、値ではなく変数自体をキャプチャします。

変数の実際の値をキャプチャするには、ローカル変数をキャプチャできる別の関数が必要です。

function makeCallback(value) {
  return function() { CallBack(value, ...) };
}

を呼び出すたびmakeCallbackに、変数の新しいインスタンスが取得されvalueます。この変数をキャプチャすると、基本的に次の値がキャプチャされます。

for(var i = 0; i < xs.length; i++)
{
    buildSelect(blah,makeCallback(xs[i]),...);
}
于 2011-02-17T04:02:09.480 に答える
0

どうやらletあなたが望むことをする新しいキーワードがあります:

for(var i = 0; i < xs.length; i++)
{
    let xm = xs[i];
    buildSelect(blah,function(){ CallBack(xm,...) },...);
}
于 2018-03-12T01:29:53.263 に答える