2011-11-21 13 views
6

でコピーされた整数の変数は、私はC#の開発者とクロージャは、C#での作業方法に使用されています。 は現在、私は匿名のjavascript機能と連携し、次のコードに問題が発生したする必要があります。アクセスはjavascriptの匿名メソッド

function ClosureTest() { 
    var funcArray = new Array(); 

    var i = 0; 
    while (i < 2) { 
     var contextCopy = i; 

     funcArray[i] = function() { alert(contextCopy); return false; }; 

     i++; 
    } 

    funcArray[0](); 
    funcArray[1](); 
} 

私は0を言うために最初funcArray()コールと1を言うために秒を期待しています。しかし、彼らはともに1と言う。そんなことがあるものか?

var contextCopy = iを書くことによって、iのコピーを作成することを確認します。次に、各反復で、私は全く新しい関数ポインタを作成します。各関数は、という独自のコピーiを参照します。ただし、何らかの理由で作成された関数は、同じcontextCopy -variableを参照しています。

JavaScriptで、このしくみを教えてください。彼らはC#でそうであるようにJavaScriptで

+0

あなたは 'for'ループを使用していない理由はありますか?ノーそこ – zzzzBov

+1

contextCopy変数の巻き上げを指摘していない;-) – TwinHabit

答えて

11

JavaScriptが字句クロージャを持って、クロージャをブロックしません。 contextCopyにiを代入しても、contextCopyはそれ自体、ClosureTestの字句メンバーです(これは{}が新しいスコープ付きブロックを与えるC#とは異なります)。これを試してみてください:

while (i < 2) { 
    funcArray[i] = (function(value) { 
     return function(){ alert(value); return false; } 
    })(i); 
    i++; 
} 
+0

のための非常に多くが、この実施例のために、ありがとうありがとう。これらの説明がここに提示された後、なぜ私の最初の試行がうまくいかないのかがわかります。 – TwinHabit

7

中括弧({})は、変数をキャプチャしません。

のみ、クロージャ(関数)新しいスコープを導入し、変数をキャプチャします。

var i = 0; 
while (i < 2) { 
    var contextCopy = i; 
    ... 
} 

実際のように解釈されます。変数のコピーを取得するには

var i, contextCopy; 
i = 0; 
while (i < 2) { 
    contextCopy = i; 
    ... 
} 

、あなたが閉鎖でコードをラップする必要があります:

var i; 
i = 0; 
while (i < 2) { 
    (function (contextCopy) { 
    ... 
    }(i)); 
} 
+1

+1である(私の答えほど明確ではありませんでした) – Matt

+0

は明確 – TwinHabit

0

あなたはしないでくださいi変数のコピーを作成します。代わりに、これを使用するクロージャのGC依存変数をこの変数にします。これは、whileループが終了すると、i変数が最後の状態(1)に存続し、両方のクロージャがそれを参照することを意味します。

もう一つの方法:変数を閉じると、クロージャーにコピーされません(オブジェクトにはほとんど意味がありません)。クロージャーが変数を参照し、クロージャーが終わるまでこの変数がGCedにならないようにします。

関連する問題