DEV Community

loading...

What Do You Know About JavaScript Closures?

spukas profile image Linas Spukas Updated on ・3 min read

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:

  1. outer function runs once and returns a closure function;
  2. outer function closes itself
  3. greeting variable became function declaration, and now has access to a closure inner and the message 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.

Discussion (2)

pic
Editor guide
Collapse
kmwill23 profile image
Kevin

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.

Collapse
heindauven profile image
Hein Dauven

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.

Collapse
sonyarianto profile image
Sony AK

Nice post, but typo on title, JavaScript instead of JavasScript :)