When I was reading some articles to be inspired and get new ideas for the following blog post to write, my eyes captured JavaScript closures. The first instinct was that I heard about it and probably know it. But when I imagine trying for someone to explain it, I realized that I really don't know what it is beside the fact that probably it is closing something in the scope... So I went back to the basics, reading articles, documentation, watching YouTube and playing PS4 in between to stay sane. And this is what I found out about this topic.
But Why You Should Care About Learning It
Job interviews for one. If you can explain one of the most confusing topics, it will strengthen your position to get a job.
The second reason, more personal for me, would be the React framework. The React Hook API and functional components are heavily based on closures. You'll have a better understanding of how the hooks operate.
So What Are Closures?
In JavaScript, closures are functions that have access to a surrounding (parent) scope. Closures are created every time when a function is created. With the help of closures, functions can hold a state or have local (private) variables, that can be accessed even after the parent function was invoked and closed.
Let's examine the following example:
function outer() {
const message = "Hello"; // local variable
function inner() { // a closure function
return message;
}
return inner;
}
const greeting = outer();
greeting() // will return a message "Hello"
Here we have a message
variable inside the outer
function. It is a local variable and cannot be accessed outside the parent function. Unless we create a closure function inner
inside the parent, that has access to the outer scope and a variable message
. Also, it is important to return closer function without invoking it.
When we assigning function outer
to the variable greeting
, a few things happen:
-
outer
function runs once and returns a closure function; -
outer
function closes itself -
greeting
variable became function declaration, and now has access to a closureinner
and themessage
variable.
Now that greeting
function became a function declaration, it can be invoked, and the returned result will be a message from the outer
function.
This might be a little bit weird, taking into consideration, that the outer
function was invoked once and closed itself. For some programming languages, local variables exist only during the lifetime of the function execution. But not in JavaScript. Here functions create closures with all surrounding environment, like variables that are in scope, at the moment they created.
The greeting
function has a reference to the closure function inner
. The latter was created during the outer
function execution and holds its environment, in which the variable message
exists.
Where Can It Be Used
Probably you already used it without knowing it, especially if you used the React framework. All event handlers of the functional components are closures.
Also, closures can be used to emulate private methods for functions, similar to class methods. For example:
function setCounter() {
let _counter = 0;
function changeCounter(value) {
_counter += value;
}
return {
increment: () => changeCounter(1),
decrement:() => changeCounter(-1),
getValue: () => _counter,
};
}
const counter = setCounter();
counter.getValue() // returns 0
counter.increment()
counter.getValue() // returns 1
In the counter example we use closures increment
, decrement
and getValue
as a public function methods. They have access to the _counter
value of the function. Besides those methods, there's no way to access the _counter
.
Let's build another stateful function:
function useState(initialValue) {
let _val = initialValue;
const state = () => _val;
const setState = (newValue) => {
_val = newValue
};
return [state, setState];
}
const [count, setCount] = useState(0);
console.log(count()) // returns 0
setCount(5);
console.log(count()) // returns 5
In the latter example we have two closure functions: state
that returns a current state of _val
variable, and a setState
which modifies _val
variable by changing its value. And it is a very very primitive implementation of the React useState
hook.
Sum Up
Closures are a difficult and interesting topic. When decided to learn and write about it, I didn't realize how broad and confusing topic it is. The examples in this article are very primitive and short ones but I hope you will get a better understanding of it, especially how the functions can hold a state.
Top comments (3)
Hard topic to explain, for sure. I actually told a really bright new dev on my team that once they have recursion figured out, we'll talk about the complexities of JS, scope, and closures.
Last year I actually started reducing the amount of closure scope I use in JavaScript. The performance benefits when browsers don't have to load scope is amazing.
Practical real world examples that allow people to achieve that 'a-ha!' moment is really key, else it's just theoretical mumbo jumbo to most.
That would make an interesting article! Performance implications of closures.
Nice post, but typo on title, JavaScript instead of JavasScript :)