Skip to content

Commit 8c1f26b

Browse files
Added detailed documentation on setTimeout and closures, including examples and explanations of common interview questions.
1 parent eed0f22 commit 8c1f26b

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

14_setTimeout_And_closures.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Episode 11 : setTimeout + Closures Interview Question
2+
3+
> Time, tide and Javascript wait for none
4+
5+
```javascript
6+
function x() {
7+
var i = 1;
8+
9+
setTimeout(function () {
10+
console.log(i);
11+
}, 3000);
12+
13+
console.log("Hello JS");
14+
}
15+
16+
x();
17+
```
18+
19+
Hello JS
20+
21+
1 //after waiting 3 seconds (3000ms)
22+
23+
We expect JS to wait 3 sec, print 1 and then go down and print the string. But JS prints string immediately, waits 3 sec and then prints 1.
24+
25+
- The function inside setTimeout forms a closure (remembers reference to i). So wherever function goes it carries this ref along with it.
26+
- setTimeout takes this callback function & attaches timer of 3000ms and stores it. Goes to next line without waiting and prints string.
27+
- After 3000ms runs out, JS takes function, puts it into call stack and runs it.
28+
29+
#### Print 1 after 1 sec, 2 after 2 sec till 5 : Tricky interview question
30+
31+
We assume this has a simple approach as below
32+
33+
```javascript
34+
function x() {
35+
for (var i = 1; i <= 5; i++) {
36+
setTimeout(function () {
37+
console.log(i);
38+
}, i * 1000);
39+
}
40+
41+
console.log("Hello JS");
42+
}
43+
44+
x();
45+
```
46+
47+
Hello JS
48+
6
49+
6
50+
6
51+
6
52+
6
53+
54+
- This happens because of closures. When setTimeout stores the function somewhere and attaches timer to it, the function remembers its reference to i, **not value of i**
55+
- All 5 copies of function point to same reference of i.
56+
- JS stores these 5 functions, prints string and then comes back to the functions. By then the timer has run fully. And due to looping, the i value became 6. And when the callback function runs the variable i = 6. So same 6 is printed in each log
57+
- **To stop this from happening, use let instead of var** as let has black scope. For each iteration, the i is a new variable altogether(new copy of i).
58+
- Everytime setTimeout is run, the inside function forms closure with new variable i
59+
- To overcome this and print the desired result we will have to use 'let' as it has block scope. So, each time the loop runs the `i` is a new variable/copy altogether.
60+
- Therefore, Each time the callback function is run, it has a new copy or new identity of `i` variable with itself.
61+
62+
**CORRECT:**
63+
64+
```javascript
65+
function x() {
66+
for (let i = 1; i <= 5; i++) {
67+
setTimeout(function () {
68+
console.log(i);
69+
}, i * 1000);
70+
}
71+
72+
console.log("Hello JS");
73+
}
74+
75+
x();
76+
```
77+
78+
Hello JS
79+
1
80+
2
81+
3
82+
4
83+
5
84+
85+
#### Using `let` instead of `var` is the best option. But if asked to use `var` only..?
86+
87+
```javascript
88+
function x() {
89+
for (var i = 1; i <= 5; i++) {
90+
function close(i) {
91+
setTimeout(function () {
92+
console.log(i);
93+
}, i * 1000);
94+
// put the setTimeout fxn inside new function close()
95+
}
96+
97+
close(i); // everytime you call close(i) it creates new copy of i. Only this time, it is with var itself!
98+
}
99+
100+
console.log("Hello JS");
101+
}
102+
103+
x();
104+
```
105+
106+
Hello JS
107+
1
108+
2
109+
3
110+
4
111+
5

0 commit comments

Comments
 (0)