Skip to main content

Closures

Closures allow functions to retain access to variables from their containing (or outer) function even after that function has finished executing.

Counter Example

function createCounter() {
let count = 0; // This is the closure variable

return function() {
count += 1; // This function has access to `count`
return count;
};
}

const counter = createCounter(); // `counter` is a function with a closure

console.log(counter()); // Output: 1
console.log(counter()); // Output: 2
console.log(counter()); // Output: 3

Closure inside Loop

for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}

/*
5
5
5
5
5
*/

//To fix this : let or IIFE

for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}

//or

for (var i = 0; i < 5; i++) {
((i) => setTimeout(() => console.log(i), 1000))(i);
}

//Print values per second
for (var i = 0; i < 5; i++) {
((i) => setTimeout(() => console.log(i), 1000 * i))(i);
}

Problem 3

function createFunctions() {
let functions = [];
for (var i = 0; i < 3; i++) {
functions.push(function() {
return i;
});
}
return functions;
}

const funcs = createFunctions();
console.log(funcs[0]()); // Output: 3
console.log(funcs[1]()); // Output: 3
console.log(funcs[2]()); // Output: 3

Hint: The var keyword has function scope, not block scope. Understand how closures capture variables and how var affects this behavior.

Problem 4

function createCounter() {
let count = 0;
return {
increment: function() {
count++;
return count;
},
reset: function() {
count = 0;
},
getCount: function() {
return count;
}
};
}

const counter = createCounter();
console.log(counter.increment()); // Output: 1
console.log(counter.increment()); // Output: 2
counter.reset();
console.log(counter.getCount()); // Output: 0

Hint: Closures allow the returned methods to access and modify the count variable even though createCounter has finished executing