What is Closure?
A closure is a function that "remembers' its lexical scope even when the function is executed outside that scope. In simple terms, closures allow inner functions to access variables from their outer (enclosing) functions even after the outer function has finished executing.
Let's Understand with examples
Example 1:function outer() {
let counter = 0; // Local variable in the outer function
return function inner() {
counter++; // Inner function has access to the outer function's variable
console.log(counter);
};
}
const increment = outer(); // 'increment' is now the inner function
increment(); // Output: 1
increment(); // Output: 2- The function
outer()is called, and a local variablecounteris initialized in its lexical environment. - Even after
outer()finishes executing, the returned inner function (assigned to the variableincrement) retains access tocounter. - This inner function forms a closure—it "closes over" its surrounding lexical scope so it can continue accessing and modifying
counterwhen invoked. - Each time you call
increment(), it increments and logs the value ofcounter, even though the outer function has long since finished. - Since
counterisn't exposed outside of the closure, it remains effectively private and cannot be accessed or modified directly from the global scope.
function outer() {
const first = 'A';
function middle() {
const second = 'B';
function innerMost() {
const third = 'C';
console.log(first + second + third); // Logs: "ABC"
}
return innerMost;
}
return middle;
}
const middleFunc = outer(); // 'middle' function
const innerFunc = middleFunc(); // 'innerMost' function
innerFunc(); // Logs: "ABC"- The function
outer()is invoked, initializingfirstin its lexical environment. - It returns
middle(), which definessecondand returnsinnerMost(). - When
innerMost()is returned and eventually invoked, it forms a closure, capturing access tofirst,second, and its ownthird. - Even though
outer()andmiddle()have finished executing,innerMost()can still reference all three variables because of this closure. - When
innerFunc()runs, it logs the concatenated result: "ABC"—demonstrating how the innermost function "remembers" values from each scope level.
Practical Use Cases of Closures
Closures are used in JavaScript for various tasks, such as creating private variables, function factories, and event handling. Here’s how closures are beneficial:
- Private Variables: Closures can help simulate private variables by creating variables that are not directly accessible from the outside.
- Function Factories: Closures can be used to create functions dynamically with different parameters.
- Event Handling: Closures are often used in event handling to maintain references to variables or state in the event callback functions.
- Callback Functions: Closures can maintain the state and context of variables inside callback functions, especially in asynchronous operations.
- Memoization: Closures help store previously computed results, improving performance by avoiding redundant calculations in recursive functions or API calls.
- Currying: Closures enable currying, where functions are created with partial arguments and the remaining arguments are provided later.
Closure Example: Creating Private Variables
function createCounter() {
let count = 0; // 'count' is a private variable
return {
increment: function() {
count++;
console.log(count);
},
decrement: function() {
count--;
console.log(count);
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment(); // Output: 1
counter.increment(); // Output: 2
console.log(counter.getCount()); // Output: 2- When
createCounter()is called, the variablecountis initialized within its lexical environment. - Even though
createCounter()finishes execution, the returned object (withincrement,decrement, andgetCountmethods) still retains references to thecountvariable. - These methods form closures—functions that "close over" their surrounding lexical scope—so they continue accessing and modifying
count, even though it would otherwise be inaccessible. - Since
countisn't exposed as a property of the returned object, it remains private and protected from direct external access or modification.