1

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

私はこのようなことをしようとしています:

var obj = function(){
    var members = ['a','b','c','d','e'];
    for(var i in members){
       inst[i] = function(){
           console.log(i);
       }
    }
};

しかし、私がそうするとき:

var inst = new obj();
inst.a(); inst.b(); inst.c(); inst.d(); inst.e();

eを5回印刷します!thisまた、オブジェクトをインスタンス化した名前を使用するのではなく、参照できる可能性がありますが、それをまったく機能させることができません。この背後にあるロジックは、WebSocketを使用してAPIテンプレートクライアント側を生成することです。これは基本的に同じタイプのことを(論理的に)行う大まかなデモですが、私はこの技術的な問題に巻き込まれていて、進行を妨げています。

ありがとう

編集

完全な問題を挙げさせてください。全員に過負荷をかけたくありませんでしたが、これらのソリューションは機能していません...

var SocketClient = function(config){
//platform specific stuff
var self = this;
var count = 0;
var socket = io.connect(config.address+':'+config.port);
var members = [];
socket.on('method',function(data){
    console.log(data.name);
    KovarApp.client[data.name] = addLogicMember(data.name);
    console.log(KovarApp.client[data.name]);
});
var addLogicMember = function(n){
    return function(config){
        var callback = null;
        if(typeof config.callback !== 'undefined'){
            var callback = config.callback;
            delete config.callback;
        }
        call({
            method: n,
            data: config,
            callback: callback
        });
    };
};
var call = function(config){
    var c = count++;
    var timer = null;
    socket.on('reply_'+c,function(data){
        if(typeof config.callback === 'function'){
            if(timer != null){
                timer.clearTimeout();
            }
            config.callback(data);
            timer = setTimeout(function(){
                socket.removeAllListeners('reply_'+c)
            },10000);
        }
    });
    config.data.handle = c; //make sure that the server has the handle for this function call
    socket.emit(config.method,config.data);
};

};

サーバーはクライアントに5つの関数を発行します。loginが最初の関数で、getpatientinfoが最後の関数です。サーバーでは、すべての応答をconsole.logに設定しています。関数のいずれかを呼び出すと、それはconsole.logのgetpatientinfoです。これは、それが受信する文字列であるためです。つまり、クライアントでは、すべての関数が最後に受信した文字列(getpatientinfo)を参照しています。いくつかの回答に従って変更しましたが、まだ機能していません。ここではソケットは問題になりません。すべてのメンバーが最後に追加されたメンバーを反映​​するため、問題は明らかにメンバーを生成するときの私のフロントエンドロジックです。

解決しました!下記参照!(これは閉鎖されませんでした!!!)

4

4 に答える 4

6

これは「クロージャー効果」と呼ばれます。各関数は、名前付きの変数を処理する必要があることを認識していますが、呼び出されたときに現在のi値を取ります。

これを解決するには、スコープも設定iします。

var makeMeAFunction = function(x) {
  return function() { console.log(x); };
};
for(var i in members){
   inst[i] = makeMeAFunction(i);
}

for...in補足として、通常、 : useforEachまたは、IE8 をサポートする必要がある場合は、従来のfor(init; check; step)演算子に頼ることで配列を反復処理することは悪い考えです。

于 2012-12-11T18:35:29.020 に答える
1

これでうまくいくはずです:

function Cn () {
    var self = this;
    [ 'a','b','c','d','e' ].forEach(function ( name, i ) {
        self[ name ] = function () {
            console.log( i );
        };
    });
}

注: IE8 の ES5-shim

于 2012-12-11T18:32:24.530 に答える
1

クロージャーに関連する問題があります -これを見て、良い記事を書いてください。

于 2012-12-11T18:35:32.180 に答える
0

問題が見つかりました。

問題はサーバー側でした。私はこれをしていました:

  for(var i in functions){
            socket.on(i,function(data){functions[i](data,socket,mysql)}); //create socket listeners
        }

私がこれに変更したとき:

        socket.on('login',function(data){functions.login(data,socket,mysql);});
        socket.on('logout',function(data){functions.logout(data,socket,mysql);});
        socket.on('getVisitInfo',function(data){functions.getVisitInfo(data,socket,mysql);});

それはうまくいきました。オブジェクトをループするのが気に入らなかったようです。まあ、私はそれが静的ソケット宣言だと思います!

于 2012-12-11T19:15:23.913 に答える