Closures in JavaScript are like secret passageways for a function to remember certain variables, even after it's done running. In this article, I'll try to answer the question "how do JavaScript closures work?" in the simplest way so you can start using them right away.
Before we move on, I want to invite you to visit 0dev, an open-source data platform that works with natural language. Use 0dev to access your data without complex SQL queries, visualize it without any coding and generate insights without any data science experience.
Repository: https://github.com/0dev-hq/0dev
Let's say you want to create a simple counter, but you don't want other parts of your code to mess with the counter's internal number. You can create a function that returns an object with methods that can change the internal number, but only the function knows about it. Here's an example:
function counter() {
let count = 0;
return {
increment: function() {
count++;
},
decrement: function() {
count--;
},
getCount: function() {
return count;
}
};
}
let myCounter = counter();
console.log(myCounter.getCount()); // 0
myCounter.increment();
console.log(myCounter.getCount()); // 1
In our example, you could say the counter
function returns an object with three methods: increment
, decrement
, and getCount
.
Each of these methods have access to the count
variable, which is defined within the parent counter
function. But, because the counter
function has completed execution, the count
variable is not directly accessible from the global scope while the inner functions still have access to it.
In other words, the returned object and its methods are closures that have access to the count
variable.
So, this was one of the common use cases of closures and now let's take a look at another example.
Another common use case for closures is to create a function that we want to pass as a callback and maintain access to variables in its parent scope. For example, take a look at this code:
function createFullName(firstName) {
return function(lastName) {
return firstName + " " + lastName;
};
}
let myFullName = createFullName("John");
console.log(myFullName("Doe")); // "John Doe"
console.log(myFullName("Smith")); // "John Smith"
In this overly simplified example, we have a function createFullName
that takes a person's first name as an argument and returns a new function which itself takes a person's last name as an argument and returns the full name.
The inner function is a closure because it "closes over" the firstName variable and remembers it, even though the parent function has finished running. This can be useful for example in a form where user fills first name and last name in two different inputs.
This technique is also one of the fundamentals of functional programming in JavaScript.
Can you add any other use cases or examples?