2017-02-26 3 views
1

私はJavascriptのクロージャを理解しようとしています。私は3つの例の下に出くわしました。
Expample 1:クロージャを理解する、繰り返しごとに異なるスコープを作成する

for (var i = 0; i <= 10; i++) { 
 
    setTimeout(function() { 
 
    console.log("i :" + i) 
 
    }, i * 1000); 
 
}

そして、それは「私の:11」印刷して期待通りに出力されているコンソールに11回を一つだけ範囲がグローバルスコープでループ全体のために作成されているため、 。各反復で異なる範囲を持つには、IIFE(すぐに呼び出される関数式)を使用しました。下記のコードをご覧ください。
例:異なる範囲を反復ごとに作成されるため、期待どおり ":0 I" "10 I" に2

for (var i = 0; i <= 10; i++) { 
 
    (function(i) { 
 
    setTimeout(function() { 
 
     console.log("i : " + i) 
 
    }, i * 1000) 
 
    })(i); 
 
}

それから印刷します。
私は以下のコードスニペットで正確に何が起こっているのか理解できません。
例: ":0 I" "I 10" を3

for (let i = 0; i <= 10; i++) { 
 
    setTimeout(function() { 
 
    console.log("i :" + i) 
 
    }, i * 1000); 
 
}

それから印刷します。
1.出力が最初の例と同じではない、つまり「1:11」の印刷が11回と同じではないことを理解できませんか?
2。ブロックスコープを使用すると、繰り返しごとに異なるスコープが作成されていますか?
3。異なるスコープが作成されている場合、example-1とどのように異なるのでしょうか?

答えて

1

letはブロックスコープ(varはありません)で動作するためです。つまり、for文を構成するコードのブロック内でローカル変数を宣言するようなものです。

たとえば、あなたがこれを行うことができます:

if (blockCount === 3) { 
    let x = 1; 
    // do something with x 
} else { 
    let x = 2: 
    // do something with x 
} 

console.log(x); // undefined since no longer in scope 

これが書かれたように動作します。 ifステートメント外のxにアクセスしようとすると、定義されません。

詳細はthis linkを参照してください。

0

最初の例では、一定時間後に変数iを出力するsetTimeout()を呼び出します。 setTimeout()コールバックが発生するまでに、ループは終了し、iは最後の反復値(11)を保持します。すべてのコールバックがその変数を出力します。

2番目の例では、直ちに呼び出される関数式(IIFE)を使用します。これは、即時に呼び出されたの関数であり、引数はiです。 引数を関数に渡すと、新しいローカル変数が宣言されたようなものになります。たとえば、次のように

var foo = 5; 
 

 
function myLog(foo) { 
 
    console.log(foo); 
 
} 
 

 
myLog("not 5"); // logs "not 5" instead of 5

これは、あなたが現在でそれを渡すので、すぐに呼び出される関数の引数iは、ループ内で使用iと異なっているが、同じ値を有することを意味しますループの反復。
この方法では、12種類の異なるi変数を作成します。 1つはループ用、11個はIIFE用です。setTimeout()コールバックが使用されています。

3番目の例でも同様のことが起こります。 letはブロックスコープローカル変数を宣言します。ループが実行されると、11種類の変数が作成され、各setTimeout()コールバックはそれぞれのローカルスコープで作成された変数を参照します。これはより完全に説明されますhere

関連する問題