2016-11-08 5 views
1

私は以下のコードを説明するために、なぜそれが意図したとおりに動作しませんどのように理解していない。これにのsetTimeoutコールバックExplination

for (var i = 0; i < 16; i++) { 

    setTimeout(function() { 
     console.log(i); 
    }, 1) 

} 

// Prints "16" 16 times 

一つの解決策は単純にforループでlet代わりのvarを使用することになり、または

for (var i = 0; i < 16; i++) { 

    (function (k) { 
     setTimeout(function() { 
      console.log(k); 
     }, 100) 
    })(i) 
} 

// Print "0" to "15" 

自己呼び出し機能です。

もし私がこれを知っているとすれば、varのスコープが関数ブロックに結びついているか、グローバルスコープとforループがsetTimeout()が生成するコールスタックを上回るJavascriptはレキシカルスコープであり、var i = 16のようにこれらの関数をすべてコールします。一方、let i = 16はそれをブロックに保持しますか?

+0

'setTimeout'は' i'が16のループの後に*を実行します。 – Li357

+0

[閉鎖の仕組み]を参照してください(http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Rajesh

答えて

0

最初の例では、ループ変数iの周りにクロージャがあります。 2番目の方法では、iのコピーを作成し、その代わりにkを使用して回避します。クロージャを避けると、すべての反復でiを共有する代わりに、各反復で独自の値を保持できます。 letを使用すると、ループ変数がiになり、ブロックレベルのスコープがあり、各反復時にiが技術的に以前のものとは異なる変数になるため、各ネストされた関数が参照を取得するため異なる値に変更します。

JavaScriptのスコープとネストされた関数がどのようにクロージャにつながるかによって、ネストされた関数が高次関数の変数を参照し、ネストされた関数の長さが親。あなたのケースでは、setTimeoutによって参照される関数は、それを含む関数より長く存続します。

関連する問題