0

I am learning event-loops JavaScript but i have found this unknown behavior of kaywords let and var using in event-loops code block. But they works fine when using them simple loops. Please help me in this regards. Code block is as follows:

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("let keyword output : ", i);
  }, 0);
}

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("var keyword output : ", i);
  }, 0);
}

Their output is as follow respectively:

let keyword output :  0
let keyword output :  1
let keyword output :  2
let keyword output :  3
let keyword output :  4

var keyword output :  5
var keyword output :  5
var keyword output :  5
var keyword output :  5
var keyword output :  5
faizan zafer
  • 3
  • 1
  • 5
  • 1
    Please read: [Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures), specifically: [Creating closures in loops: A common mistake](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#creating_closures_in_loops_a_common_mistake). For in-depth details, read: [Closures in loops problem and how it is solved in ES6](https://blog.yousafkhan.me/understanding-closures-in-loops-problem-and-how-it-is-solved-in-es6) – Yousaf Aug 23 '21 at 06:51
  • Here is an article explaining this behaviour https://betterprogramming.pub/scoping-in-javascript-for-loops-c5ffac6aa92b – ziishaned Aug 23 '21 at 06:56

2 Answers2

2

The difference is in the scope of var and let variables.

With var you have a function scope and therefore only one shared binding. With let you have a block scope and you get for each iteration a new binding.

Because of the closure, the function you declare inside the loop has access to all the variables in its scope and parents scopes until the garbage collector is on.

More details can be found on this answered question.

FloWy
  • 934
  • 6
  • 14
0

when you define a variable with "var" your variable scope is function scope or if it's declared outside of a function it would be global scope. in your example first all your synchronous code will executed and all setTimeOut() will be moved to "callback queue" then after all synchronous codes are finished and the main is clear then setTimeOuts (asynchronous code) will be pushed to main and executed one by one .

var : when you declered "i" with "var" as i mentioned it's function scope the and because declaration of "i" is not inside of different functions it will be global scope and the value for all the logs would be the last value "for" loop assigned to it (5).

let : when you declare "i" with "let" it's block scope and because the logs are in different blocks the value of "i" for each log would be different.

the difference between "let" and "var" is nothing to do with event loop this asynchronous example just showed you the difference. try this you will see the value for "j" is different for every log :

for (var i = 0; i < 5; i++) {
  let j = i;
  setTimeout(() => {
    console.log("var keyword output : ", i, j);
  }, 0);
}

it means "i" has different value in every iteration but because it's value is overwrite in the next iteration and it's global scope the value that will log for all logs are the last one and same

siamak
  • 106
  • 4