+ 12

I need help from js experts

How does this code print "3, 3, 3" and not "0, 1, 2"? It works when you change the "var" with "let" but I still cant see the difference. Pls some one explain! https://code.sololearn.com/WdSI3g7iRyQk/?ref=app

28th Apr 2019, 7:23 AM
Alfa Melake🇪🇹
Alfa Melake🇪🇹 - avatar
20 Réponses
+ 15
[Part 1] This is a good question, it gave me hard times when I faced this doubt. To understand this completely we first need to make sure we understand these 2 concepts. 1. How Scopes work differently for "let" & "var"? 2. How setTimeout() method works? To understand this we need to know the concept of "event loops" in JavaScript. I ll write a 4 part answer below, this being the first part. 2nd part - let vs var 3rd part - quick intro on asynchronous operations using event loops 4th part - binding it all together to finally answer your question [Continued in Part 2]
28th Apr 2019, 8:11 AM
Morpheus
Morpheus - avatar
+ 14
[Part 2] : Let Vs Var Here is a code going through the 4 differences between the 2 https://code.sololearn.com/WdGAFeNRAe9M/#js The important conclusion to take from above code is the first difference. var is function scoped, which means local scope of variables created by var keyword is only effective inside function blocks. Therefore the variables declared using var inside for loop block will be in global scope. for(var i =0; ; ){ } is same as var i =0; for(i =0; ;){} whereas let is block scoped, which means any curly braces {} can create a local scope for variables declared using let keyword. It doesnt matter where the curly braces are coming from it ll be same for all i.e - function(){} - for(;;){} - if(){} - or just {} [Continued in Part 3]
28th Apr 2019, 8:41 AM
Morpheus
Morpheus - avatar
+ 13
var is global variable, for timer functions that going to be executed later, the functions would use the var i which is the last iterated value, since it is overwritten to the last value, before the timer functions run. To prove i is a global variable, I take your code for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 1000); } i = 1000; // add another last value here. This code would output 1000 1000 1000 1000 https://code.sololearn.com/WG2AX2GfqWZG/?ref=app
28th Apr 2019, 7:57 AM
Calviղ
Calviղ - avatar
+ 13
[Part 4] : Grand Finale We know now that how let and var behaves differently var -> creates global scope variables inside for(;;){} let -> creates local scope variables inside for(;;){} we also know that async codes are skipped and executed after synchronous codes in next event loops, so all the code inside the setTimeout() block will be executed after 1 second when we have completed the other code i.e looping through the for loop 3 times. Now we can have an interpretation of how JS-Engine sees the code, which is demonstrated here in this code. https://code.sololearn.com/Wh2ENDDNg9V5/?ref=app Important Note: Although this will complicate the answer unnecessarily but I would like to highlight that the inner working of let to create a local scope is merely a hack. Unlike other languages where rather than declaring a variable once and incrementing it, let variables are declared again and again. https://stackoverflow.com/questions/16473350/let-keyword-in-the-for-loophow
28th Apr 2019, 10:19 AM
Morpheus
Morpheus - avatar
+ 12
let i defines i in block scope, each iteration is a separated block scope for i, thus you still can get the difference i values in timer functions later. https://code.sololearn.com/WXdVtq9sS5m0/?ref=app For more information https://wesbos.com/for-of-es6/
28th Apr 2019, 7:59 AM
Calviղ
Calviղ - avatar
+ 11
[Part 3] : setTimeout() In Javascript at the heart of the JS engine there is a mighty loop called "Event Loop". The basic concept behind event loop is to make all the time taking operations as asynchronous(aka async). setTimeout() is also an async method. so while running a JS code whenever an async method is encountered then the JS engine skips that code and mark it as "I ll run you later on when I have been through all the code && you are done(i.e some event is fired)". I know I did a terrible job in explaining specially the meaning of Asynchronous, but I ll highly suggest to go through this article for a better understanding. https://hackernoon.com/understanding-js-the-event-loop-959beae3ac40 Back to our code, so every time setTimeout is encountered inside for loop, it is just being ignored until we reach the end of the code. In later event loops after 1sec JS engine realizes that "Oh the setTimeout part is still pending 3 times. so it executes the console.log(i) 3 times [Continued in Part 4]
28th Apr 2019, 9:12 AM
Morpheus
Morpheus - avatar
+ 7
Please read the reference materials shared by everything.js every day, especially the concept of scope, closures and event loop. https://www.sololearn.com/post/91896/?ref=app
28th Apr 2019, 8:53 AM
Gordon
Gordon - avatar
+ 7
Awesome answers!... but if you still want to get deeper into var, let and const, you could check out my blog. https://code.sololearn.com/WdauYjg8rOiF/?ref=app
29th Apr 2019, 7:41 AM
Benneth Yankey
Benneth Yankey - avatar
+ 6
interesting ... Biraj
28th Apr 2019, 8:57 AM
Prashanth Kumar
Prashanth Kumar - avatar
+ 5
Morpheus thank you very much! That was very helpful.
28th Apr 2019, 10:46 AM
Alfa Melake🇪🇹
Alfa Melake🇪🇹 - avatar
+ 4
Asmerom Estifanos In the code shared by Alfa, the timeout period is fixed 1 second, so all console.log(i) will happen after 1 sec but we can make it variable to give output in 1 second gaps like this. for (let i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, (i + 1) * 1000); } Note that even if you use var here, the behavior will still be the same but we ll just get three '3' in 1 sec delay each. Btw, i encountered this problem presented by you myself when I was trying to do what you were trying to do in this code. It was an attempt to make timed presentation out of html. https://code.sololearn.com/WGGbx9i3f01C/?ref=app
28th Apr 2019, 3:08 PM
Morpheus
Morpheus - avatar
+ 4
Thanks a lot Morpheus for taking your time...That was very helpful!!!
28th Apr 2019, 3:32 PM
Asmerom Estifanos
Asmerom Estifanos - avatar
+ 4
Biraj no need to wrap the setTimout function inside an IIFE you can just pass the i index as an argument to the setTimeout function for later use: for (var i = 0; i < 3; i++){ setTimeout(function(i) { console.log(i); }, 1000, i); }
28th Apr 2019, 5:00 PM
SalahDEV
SalahDEV - avatar
+ 4
Morpheus you have really broken down the whole question.. Thanks, it was very valuable info.
4th Aug 2019, 10:17 PM
Charnel
Charnel - avatar
+ 2
Morpheus I have one tiny question, how can we output 0,1 & 2 every one second? I mean put a one second gap between the three outputs?
28th Apr 2019, 2:38 PM
Asmerom Estifanos
Asmerom Estifanos - avatar
+ 2
Biraj my pleasure brother.
28th Apr 2019, 5:02 PM
SalahDEV
SalahDEV - avatar
+ 1
This is a good question, it gave me hard times when I faced this doubt. To understand this completely we first need to make sure we understand these 2 concepts. 1. How Scopes work differently for "let" & "var"? 2. How setTimeout() method works? To understand this we need to know the concept of "event loops" in JavaScript. I ll write a 4 part answer below, this being the first part. 2nd part - let vs var 3rd part - quick intro on asynchronous operations using event loops 4th part - binding it all together to finally answer your question Next...
28th Apr 2019, 2:23 PM
Akul Vai
Akul Vai - avatar
0
I don't know if I have done that correctly, but I made a demonstation of what kind of happens behind the scenes, I will post it here since it may be helpful: https://code.sololearn.com/WgwRxAY2IHNq/?ref=app
8th Dec 2020, 7:12 PM
Karak10
Karak10 - avatar