简体   繁体   中英

Why variable value is different incase of var and let in setTimeout

While practicing JavaScript, I came across with one doubt I am printing variable i value using var and using let keyword and both the time getting different result but unable to understand why I need some explanation for this??

Declaring i as let :

<script>
(function timer() {
  for (let i = 0; i <= 5; i++) { 
    setTimeout(
      function clog() {
        console.log(i);
      }, i * 1000
    ); 
  }
})();
</script>

The output is a count from 0 to 5:

Declaring i as var , on the other hand:

<script>
(function timer() {
  for (var i = 0; i <= 5; i++) { 
    setTimeout(
      function clog() {
        console.log(i);
      }, i * 1000
    ); 
  }
})();
</script>

The output is 6 times a 6:

The reason is simple. let is block scoped. It means that when you get out of the scope of your for loop, it does not exist. var scope is wider. What happens here is that the for loop increments i 5 times, then gets out of the loop with i = 6 before the first setTimeout triggers (in less than 1 second) with a global scope. The i declared with let is from the function scope, while the i declared with var is from the outer scope

Difference between let and var: What is the difference between "let" and "var"?

With for loop, each iteration has its own scope .

  1. In the case of let as its block scope each iteration will have its own i variable and its value will be closure in the setTimeout , so each setTimeout will output the correct index

  2. In the case of var as it's a functional scope , each iteration will override the previous one, and at the time of execution of the setTimeout the value of i will be 6 at the end of the iteration, will be logged in all setTimeout callbacks.

The scope of i is different when using let and when using var

Here:

for(let i=0;i<=5;i++){ // i will not be available outside of the block below

setTimeout(
function clog(){
console.log(i)

},i*1000 ); 
// mentionning the variable i will cause a Reference error starting from here

Whereas with var , i gets hoisted, and defined without a value at the beginning of current the function's block, at the end of the loop i still exists, and has been mutated, so by the time the setTimeout callback is triggered, the loop will be already finished and i will have its final value, which is the first value not matching the looping condition (ie 6 ).

It is because of globally (var) or block scoped (let) value processing of javascript.

In var, variable i is globally changing and the loop finishes before settimeout function runs, so the i becomming 6 globally and console log writes yo it as 6.

In let, for every loop iteration there is an i variable belongs only that scope and settimeout function takes it, so the even if the loop finish it's job console log writes local varible i as 0,1,2,3,4,5.

I hope i tell myself correctly.

ref: Javascript MDN

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM