2017-12-28 25 views
4

私はletにブロックスコープがあり、varには機能スコープがあることを理解しています。しかし、私はこのケースでは理解していない、レットを使用して、問題javascriptでvs varを聞かせて

const arr = [1,2,3,4]; 
for (var i = 0; i < arr.length; i++) { 
setTimeout(function() { 
    console.log(arr[i]) 
}, 1000); 
} // Prints undefined 5 times 

const arr = [1,2,3,4]; 
for (let i = 0; i < arr.length; i++) { 
setTimeout(function() { 
    console.log(arr[i]) 
}, 1000); 
} // Prints all the values correctly 

答えて

1

まず、出力は4回ではなく(あなたのコメントで述べたように)の5倍になります。 私はバベルREPLで自分のコードを貼り付け、これは私が得たもので、

"use strict"; 

var arr = [1, 2, 3, 4]; 

var _loop = function _loop(i) { 
setTimeout(function() { 
    console.log(arr[i]); 
}, 1000); 
}; 

for (var i = 0; i < arr.length; i++) { 
_loop(i); 
} 

あなたはどのように内部的に動作するようになりました聞かせて参照していますか? :-)

0

を解決する方法あなたはまだsetTimeoutためvarを使用することができます。直ちに呼び出される関数式(IIFE)を使用して、setTimeout関数によって値iが認識されるように、setTimeoutの周りにクロージャを作成できます。

const arr = [1,2,3,4]; 
 
for (var i = 0; i < arr.length; i++) { 
 
(function(i){ 
 
setTimeout(function() { 
 
    console.log(arr[i]) 
 
}, 1000)})(i); 
 
}

+4

これは、「なぜ動作させるのか」という質問には答えません。 – Amadan

+0

答えAnkitに感謝します。しかし、私はそれがIIFEを使用して動作させる方法を知っています。私はちょうど 'let'がこの仕事をする方法を疑問に思っています。 – Krishna

3

これは、変数のスコープに関連するすべてです。のは、関数に作品の両方をラップし、出力を観察してみましょう:

function test() { 
 
    // `i` will be declared here, making it a non-for-loop scoped variable 
 
    const arr = [1, 2, 3, 4]; 
 
    for (var i = 0; i < arr.length; i++) { 
 
    setTimeout(function() { 
 
     console.log(arr[i]) 
 
    }, 1000); 
 
    } // Prints undefined 5 times 
 
} 
 

 
test();

だから、最初のケースでは、iが掲揚、およびのでsetTimeoutの非同期性のものであろう、iがします待たずにループが終了するとすぐに4になります。これにより、arr[i]は配列内のundefined要素を指すようになります。

第2のケースでは、iはループされておらず、ループの各繰り返しに対して有効範囲が設定されているため、console.logステートメントではiが正確に使用できます。このような結果は期待通りです:すべての

function test() { 
 
    const arr = [1, 2, 3, 4]; 
 
    for (let i = 0; i < arr.length; i++) { 
 
    setTimeout(function() { 
 
     console.log(arr[i]) 
 
    }, 1000); 
 
    } // Prints all the values correctly 
 

 
} 
 

 
test();

+1

私はまだそれを得ることはありません。 'のために' 'は'のために、 ''のためにスコープされていますか? 4つの異なる「i」または「1つ」がありますか?もしあれば、 'var'の状況とどう違うのですか(おそらく' i'は 'var'のようにクロージャで捕捉されるでしょう)? 4つの場合、なぜ「i ++」が機能するのですか(つまり古い「i」と新しい「i」の両方がどのようにアクセスされますか)?もし誰かがES2018の関連するパッセージを持っていれば、それは驚くべきことでしょう。 (編集:提案された複製は答えを持っています。) – Amadan

+0

うん、私はそれを手に入れませんでした。 *吊り上げた*が何を意味するのか説明できますか? –

+0

'2番目のケースでは、私は吊り上げられておらず、ループの各反復に対してスコープを設定していますので、console.logステートメントで正確に利用できるようになりました。それは正しいですが、ループの実行は' setTimeout'この場合もループは終了し、settimeoutの外側に 'i'の値を記録すると、' settimeout'が実行を開始する前に値 'i'が' length-1'に設定されていることがわかります。ですから、 'settimeout'は値が' length-1'に設定されていても 'i'の値を得る方法です。 – brk

関連する問題