Skip to content

Commit 58756b9

Browse files
closure interview questions
1 parent 1ae2fb7 commit 58756b9

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed

JS Interview Question/closures.md

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
# JavaScript Interview Questions: Closures Edition
2+
3+
4+
---
5+
6+
## Q1: What is a Closure in JavaScript?
7+
**A:**
8+
A closure is a function along with a reference to its outer environment. In other words, a closure is a combination of a function and its lexical scope bundled together.
9+
10+
**Example:**
11+
```js
12+
function outer() {
13+
var a = 10;
14+
function inner() {
15+
console.log(a);
16+
} // inner forms a closure with outer
17+
return inner;
18+
}
19+
outer()(); // 10
20+
```
21+
- Here, `outer()` returns `inner`, and calling it prints `10` because `inner` has access to `a` from its outer scope.
22+
23+
---
24+
25+
## Q2: Does the order of variable declaration matter for closures?
26+
**A:**
27+
No, the inner function forms a closure with its outer environment, so the sequence doesn't matter.
28+
29+
**Example:**
30+
```js
31+
function outer() {
32+
function inner() {
33+
console.log(a);
34+
}
35+
var a = 10;
36+
return inner;
37+
}
38+
outer()(); // 10
39+
var close = outer();
40+
close(); // 10
41+
```
42+
43+
---
44+
45+
## Q3: Does changing `var` to `let` affect closures?
46+
**A:**
47+
No, the closure will still work the same way.
48+
49+
**Example:**
50+
```js
51+
function outer() {
52+
let a = 10;
53+
function inner() {
54+
console.log(a);
55+
}
56+
return inner;
57+
}
58+
outer()(); // 10
59+
```
60+
61+
---
62+
63+
## Q4: Do closures capture function arguments?
64+
**A:**
65+
Yes, inner functions have access to their outer function's arguments.
66+
67+
**Example:**
68+
```js
69+
function outer(str) {
70+
let a = 10;
71+
function inner() {
72+
console.log(a, str);
73+
}
74+
return inner;
75+
}
76+
outer("Hello There")(); // 10 "Hello There"
77+
```
78+
79+
---
80+
81+
## Q5: Can closures access variables from multiple outer scopes?
82+
**A:**
83+
Yes, closures can access variables from all their parent scopes.
84+
85+
**Example:**
86+
```js
87+
function outest() {
88+
var c = 20;
89+
function outer(str) {
90+
let a = 10;
91+
function inner() {
92+
console.log(a, c, str);
93+
}
94+
return inner;
95+
}
96+
return outer;
97+
}
98+
outest()("Hello There")(); // 10 20 "Hello There"
99+
```
100+
101+
---
102+
103+
## Q6: What if there are conflicting variable names in the scope chain?
104+
**A:**
105+
The inner function will use the closest variable in its scope chain. If not found, it will look further out.
106+
107+
**Example:**
108+
```js
109+
function outest() {
110+
var c = 20;
111+
function outer(str) {
112+
let a = 10;
113+
function inner() {
114+
console.log(a, c, str);
115+
}
116+
return inner;
117+
}
118+
return outer;
119+
}
120+
let a = 100;
121+
outest()("Hello There")(); // 10 20 "Hello There"
122+
```
123+
- Here, `a` inside `outer` shadows the global `a`.
124+
125+
---
126+
127+
## Q7: What are the advantages of closures?
128+
- Module Design Pattern
129+
- Currying
130+
- Memoization
131+
- Data hiding and encapsulation
132+
- setTimeouts and async code
133+
134+
---
135+
136+
## Q8: How do closures help with data hiding and encapsulation?
137+
138+
**Without closures:**
139+
```js
140+
var count = 0;
141+
function increment() {
142+
count++;
143+
}
144+
// Anyone can access and modify count
145+
```
146+
147+
**With closures:**
148+
```js
149+
function counter() {
150+
var count = 0;
151+
function increment() {
152+
count++;
153+
}
154+
}
155+
// count is not accessible from outside
156+
```
157+
158+
**With closure and function return:**
159+
```js
160+
function counter() {
161+
var count = 0;
162+
return function increment() {
163+
count++;
164+
console.log(count);
165+
}
166+
}
167+
var counter1 = counter();
168+
counter1(); // 1
169+
var counter2 = counter();
170+
counter2(); // 1 (separate instance)
171+
```
172+
173+
**With constructor for scalability:**
174+
```js
175+
function Counter() {
176+
var count = 0;
177+
this.incrementCounter = function() {
178+
count++;
179+
console.log(count);
180+
}
181+
this.decrementCounter = function() {
182+
count--;
183+
console.log(count);
184+
}
185+
}
186+
var counter1 = new Counter();
187+
counter1.incrementCounter();
188+
counter1.incrementCounter();
189+
counter1.decrementCounter();
190+
// 1 2 1
191+
```
192+
193+
---
194+
195+
## Q9: What are the disadvantages of closures?
196+
Closures can cause overconsumption of memory because closed-over variables are not garbage collected until the closure is released. This can lead to memory leaks if not handled properly.
197+
198+
**Example:**
199+
```js
200+
function a() {
201+
var x = 0;
202+
return function b() {
203+
console.log(x);
204+
};
205+
}
206+
var y = a();
207+
y(); // x is not garbage collected as long as y exists
208+
```
209+
210+
**Garbage Collector:**
211+
JavaScript engines automatically free up unused memory, but closed-over variables remain as long as the closure exists. Modern engines are smart and will only keep variables that are actually referenced by the closure.
212+
213+
---
214+
215+
## Q10: setTimeout, Closures, and Loop Pitfalls
216+
217+
### The Problem with `var` in Loops
218+
```js
219+
function y() {
220+
for (var i = 1; i <= 5; i++) {
221+
setTimeout(() => {
222+
console.log(i);
223+
}, i * 1000);
224+
}
225+
}
226+
// y();
227+
```
228+
- This will log `6` five times. Why? Because `var` is function-scoped, so all callbacks share the same `i`.
229+
230+
### Fix with IIFE
231+
```js
232+
function z() {
233+
for (var i = 1; i <= 5; i++) {
234+
(function(closeI) {
235+
setTimeout(() => {
236+
console.log(closeI);
237+
}, closeI * 1000);
238+
})(i);
239+
}
240+
}
241+
// z();
242+
```
243+
- The IIFE captures the current value of `i` for each iteration.
244+
245+
### Fix with `let`
246+
```js
247+
function a() {
248+
for (let i = 0; i < 5; i++) {
249+
setTimeout(() => {
250+
console.log(i);
251+
}, i * 1000);
252+
}
253+
}
254+
// a();
255+
```
256+
- `let` is block-scoped, so each callback gets its own `i`.
257+
258+
---
259+
260+
## Summary
261+
Closures are a fundamental concept in JavaScript, enabling powerful patterns like data hiding, currying, and async programming. Understanding closures is essential for interviews and real-world coding.

0 commit comments

Comments
 (0)