Difference between var and let keyword in JavaScript in calling asynchronous functions

Consider below code snippet – it just has couple of for loops. Everything is same except for the fact that the first for loop uses ‘var’ keyword and second for loop uses ‘let’ keyword.

Would there be any difference in ‘console.log’ statements between first loop and second loop? Take your time and answer.

Answer: The first loop will print 3 3 3 whereas the second loop will print 0 1 2

You need to understand below JavaScript concepts to truly understand above code snippet

  1. Asynchronous nature of JavaScript
  2. Difference between ‘var’ and ‘let keyword

Please read that asynchronous nature of JavaScript post before proceeding further. Done? Let’s proceed.

Below is the sequence of events that happen when first for loop is executed (lines 1 to 3)

  1. Let’s start at the beginning. We’re in first iteration of the ‘for’ loop (with value of variable ‘i’ being zero) and we’re calling ‘setTimeout’ function of javascript.
  2. This ‘setTimeout’ function is an asynchronous function. This function will interact with browser environment to create a ‘timer’. The information passed to the timer are callback function (arrow function with console.log statement in our case) and the time period (zero milliseconds in our case) after which the function has to be called.
  3. Once the time period is elapsed, which would happen immediately as we’ve mentioned zero milliseconds, browser would NOT execute the function immediately. Instead the callback function would be placed in queue called ‘callback queue’, as explained in this post.
  4. The items(callback functions) in the ‘callback queue’ would be pushed to the javascript runtime environment only if the call stack is empty. As there are couple of iterations and another for loop statement are waiting to be executed, the call stack would not be empty.
  5. Above mentioned steps from 2 to 4 happen for each iteration with value for ‘i’ being 1 and 2

Whatever we’ve discussed for the first for loop would apply for the second for loop too (lines 5 to 7) – Calling setTimeout function which in turn will create a timer which in turn will place the callback function in the callback queue.

Now, we’ve 6 items available in callback queue. The first 3 items are the callback functions corresponding to the first for loop (lines 1 to 3) and the next 3 items correspond to the callback functions generated by second for loop (lines 5 to 7).

As there are no more statements waiting to get executed, callback functions from the callback queue would get start executed one by one. Below is the first callback function to be executed. This function is passed from line 2 of the earlier code snippet, that we saw.

In the first for loop, variable is declared using ‘var’ keyword. Variables declared using ‘var’ keyword are function scoped. As our first ‘for’ loop is not enclosed within any function, the variable is global, and the value of this global variable was incremented at each iteration of the first for loop. At the end of the first for loop, the variable ‘i’ will have the value of 3 as the value is overwritten at each iteration of the first for loop. So, at the time of execution of the first callback function from the ‘callback queue’, the value of ‘i’ will be 3.

So, the first callback function will print numeric value 3 at console. The second and third callback function will also print the same numeric value 3 as it points the same variable.

But in the case of second for loop, we’ve used ‘let’ keyword to declare the variable. Variables declared using ‘let’ keyword are block scoped. A block is nothing but a pair of curly braces. So, in second for loop, a new value is used for each iteration. So, the last 3 callback functions will have the numeric values 0, 1, 2 respectively for the variable ‘i’ and hence would print 0, 1 and 2.

We can make the callback function to use the new variable value every time using ‘var’ keyword itself. As variables in javascript are function scoped (unless you use ‘let’ or ‘const’ keyword), you can call a function by passing the iteration variable. This will create a new variable every time.

Consider below code snippet – we’re still using for loop with ‘var’ keyword but instead of calling ‘setTimeout’ function directly, we’re calling ‘setTimeout’ function through another function.

What happens here is that – at each iteration, we’re calling ‘callSetTimeout’ function by passing the iteration variable. At each iteration, a new variable is created with the scope of function ‘callSetTimeout’ and ‘setTimeout’ function is called with new variable. The callback functions would use these variables and would print 0 1 2.

With respect to asynchronous function, this is the difference between variables created using ‘var’ keyword and ‘let’ keyword. Hope you enjoyed this post. Please let me know your thoughts in comments.