Let's understand what JavaScript Closures are.
Piyush Sharma
Posted on October 27, 2023
If you are learning JavaScript, there is no chance that you haven't heard about closures. Closures are one of the most important topics that also help you master other advanced topics. In the beginning, they may seem very overwhelming, but once you understand them, they become quite easy.
What are closures, anyway? 🤔
Closures refer to functions that are bundled (enclosed) together with their parent's lexical scope and have access to that parent's lexical scope even after the parent function has executed. In other words, even after the parent function goes out of execution, the closure can still access the variables and methods defined inside it.
Let's understand this using an example. Suppose we have a variable, say, globalVariable, in the global scope, and an outer function which has another variable, localVariable, inside it. Now, the localVariable can only be accessed inside the outer function.
let globalVariable = 43; // can be accessed anywhere in the code
const outerFunction = () => {
let localVariable = 27; // can be accessed only inside outerFunction()
};
Now let's suppose we have an inner function inside the outer function.
let globalVariable = 43;
const outerFunction = () => {
let localVariable = 27;
function innerFunction(){}
};
At this point of time the inner function has access to both localVariable and globalVariable, why? Because innerFunction() has access to its parent's lexical environment.
Lexical Environment of outerFunction()
-> globalVariable
-> localVariable
Now if we try to log the values of globalVariable and localVariable in the console we will get 43 and 27.
let globalVariable = 43;
const outerFunction = () => {
let localVariable = 27;
function innerFunction(){
console.log(`Inner -> Global Variable: ${(globalVariable)}`);
console.log(`Inner -> Local Variable: ${(localVariable)}`);
}
};
Till now, everything is pretty simple, right? So, what exactly is a closure here?
In this example, the innerFunction() has a closure over its parent's lexical environment.
Every time a function is created, a closure is also created along with it.
Now, if we return this innerFunction() and assign it to some other variable, we can still access the localVariable outside the outerFunction().
let globalVariable = 43;
const outerFunction = () => {
let localVariable = 27;
return function innerFunction(){
console.log(`Inner -> Global Variable: ${(globalVariable)}`);
console.log(`Inner -> Local Variable: ${(localVariable)}`);
}
};
const result = outerFunction(); // this will contain the inner function
We can now also modify the local variable through the closure, like this:
const innerFunction = () => {
console.log(`Inner -> Global Variable: ${(globalVariable += 1)}`);
console.log(`Inner -> Local Variable: ${(localVariable += 1)}`);
};
Closures using IIFE (Immediately Invoked Function Expression)
const playGame = (() => {
let tokenCounter = 5;
console.log(`Start Game. Tokens available: ${tokenCounter}`);
return function () {
if (tokenCounter === 0) {
console.log(`No more tokens available.`);
} else {
console.log(`Token(s) available: ${(tokenCounter -= 1)}`);
}
};
})();
playGame();
In this example, the playGame() function has a closure over the variable tokenCounter, enabling it to modify the value of tokenCounter, which cannot be accessed otherwise.
Applications of closures
- Data encapsulation
- Event handlers
- Callbacks
- Currying
- and many more..
Well, there is much more to discuss about closures, which I will try to cover in another post. Try to go over the examples again and read the official documentation to gain a solid grasp of closures.
Happy Coding💻
Posted on October 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.