What is Javascript Closure
Closure means that an inner function always has access to the variables and parameters of its outer function, even after the outer function has returned.
When inner function declare another variable with the same name, the local variable will be used instead of outer’s one
function buildGreeting(message: string) {
return function (audience: string) {
return message + ' ' + audience;
};
}
let english = buildGreeting('Hi');
console.log(english('Peter'));
Output: Hi Peter
Closure and Loops
Sometimes, Closure leads to an unexpected result
for (var id = 0; id < 3; id++) {
setTimeout(function () {
console.log('seconds: ' + id);
}, id * 1000);
}
Output:
seconds: 3
seconds: 3
seconds: 3
Because all three iterations of the loop share the same scope, the setTimeout function creates a closure shared by each loop
The setTimeout function uses a callback, and by the time the callback is executed, the loop has already completed, so 'id' will always be 3 in all setTimeout callbacks.
ES6 let keyword
for (let id = 0; id < 3; id++) {
setTimeout(function () {
console.log('seconds: ' + id);
}, id * 1000);
}
Output:
seconds: 0
seconds: 1
seconds: 2
The use of 'let' creates a block-scoped variable, fixing the closure issue. Now each setTimeout callback captures the correct value of 'id'.
Closure and IIFE
Another way to avoid this issue with closures in a loop is to use the IIFE (Immediately Invoked Function Expression) syntax
for (var id = 0; id <= 3; id++) {
// Using an immediately-invoked function expression (IIFE) to create a new scope for each iteration.
// This helps avoid the closure issue with setTimeout.
(function (id) {
setTimeout(function () {
console.log('seconds: ' + id);
}, id * 1000);
})(id);
}
Advantages of closures
- Lexical Scoping: Closures use lexical scoping, meaning they capture and remember the variables in the scope where they are created
- Function Factory: Closures are often used to create function factories, where a function generates and returns another function with specific behavior. This is useful for creating functions with different configurations based on the arguments passed to the outer function
- Callback Functions: Closures are commonly used for creating callback functions. Functions can be passed as arguments to other functions and still retain access to the variables from their original scope
- Partial Application and Currying: Closures enable techniques like partial application and currying, allowing functions to be partially applied with specific arguments, leading to more modular and reusable code
Disadvantages of closures
- Memory Usage: Closures can lead to increased memory usage, as the inner function retains a reference to the variables in its outer scope, preventing them from being garbage collected. This can potentially lead to memory leaks if closures are not managed properly.
- Potential for Bugs: Closures can introduce the possibility of bugs, especially if developers are not careful with variable scope and unintentionally modify shared variables