Wanna see something cool? Check out Angular Spotify 🎧

What is JavaScript Closure?

I still remember an interview with the customer five years ago when I worked in Hanoi. I was just graduated from university at that time and didn’t have much experience.

There were some basic questions such as "1" + 1 will evaluate in what value?. I knew the answer is "11" but have no idea what is type coercion and why the value is "11".

And then the guys started asking about Closure. I answered in a very naive way It is a function which is return in another function.... The guys on the phone weren’t laughing but I know that I was wrong. I only read about Closure from w3schools before.

Closure is not easy to digest. It has always been a bit of a mystery to me. I have read multiple articles, I have used closures in my work, sometimes I even used a closure without realizing I was using a closure. After more than four years working with JavaScript and has built many applications from small to large scale that serve ten of thousands of users, I hope that I can properly answer this question.

Many parts of this blog post are heavily influenced by and taken from an excellent article on MDN.

Execution context

Some concepts are important to understand before you can fully get the idea of closures. One of them is the execution context. This article has a very good primer on Execution Context.

What is JavaScript Closure?

What is a Closure?

Consider the following example

//sum: outer function
function sum(a) {
  //add: inner function
  return function add(b) {
    return a + b
  }
}

var sumTwo = sum(2)
var sumOfTwoAndThree = sumTwo(3) //5
  1. Function sum was created with an argument a. When invoke sum, it will return another function add that has b as the local argument. Noted that how add also has access to a, which is the argument of the outer function sum.
  2. I created a variable sumTwo and assigned it to the return value of sum(2). At this point, sumTwo is actually another function that can be invoked, which is add(b).
  3. I created another variable sumOfTwoAndThree and assigned it to the return value of sumTwo(3), which is 5.

It means that somehow, the sumTwo function still has access to 2, and then do the add operation with 3 that I passed in.

Where is the value 2 of an argument a stored, even the function sum has already been executed and its value was assigned to sumTwo?

In some programming languages, the local variables within a function exist for just the duration of that function’s execution. Once sum() finishes executing, you might expect that the a argument would no longer be accessible. However, because the code still works as expected, this is obviously not the case in JavaScript.

The reason is that functions in JavaScript form closures.

A closure is a combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. Even when the outer function has already been invoked and returned.

In JavaScript, closures are created every time a function is created, at function creation time.

Whenever you declare a new function and assign it to a variable, you store the function definition, as well as a closure. The closure contains all the variables that are in scope at the time of creation of the function. It is analogous to a backpack. A function definition comes with a little backpack. And in its pack it stores all the variables that were in scope at the time that the function definition was created.

What is JavaScript Closure?

Look at the above screenshot from VSCode debugger, you will see that when invoked the sumTwo(3), the closure contains a : 2. While the local scope contains b : 3.

You could also invoke the function differently.

//sum: outer function
function sum(a) {
  //add: inner function
  return function add(b) {
    return a + b
  }
}

sum(2)(3)

// Is equivalent to...
sum(2)
function add(b) {
  return 2 + b
}
add(3)

// Which becomes...
return 2 + 3 // 5

Usage

Emulating private methods with closures

I usually rely on Revealing Module Pattern to have the ability to define private property and method. One of the examples I have already published, you can read Limit the number of simultaneous ajax requests.

I only exposed the addRequest to the outside world. The rest will stay inside the closure and nobody else can access it. By doing so, I have control over my code, and also don’t pollute the global context by introducing global variables.

Event handler

Much of the code written in front-end JavaScript is event-based. You define some behavior, and then attach it to an event that is triggered by the user (such as a click or a keypress). The code is attached as a callback (a single function that is executed in response to the event).

For instance, suppose we want to add buttons to a page to adjust the text size. One way of doing this is to specify the font-size of the body element (in pixels), and then set the size of the other elements on the page (such as headers) using the relative em unit:

body {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 12px;
}

h1 {
  font-size: 1.5em;
}

h2 {
  font-size: 1.2em;
}

Such interactive text size buttons can change the font-size property of the body element, and the adjustments are picked up by other elements on the page thanks to the relative units.

Here’s the JavaScript:

function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + 'px'
  }
}

var size12 = makeSizer(12)
var size14 = makeSizer(14)
var size16 = makeSizer(16)

size12, size14, and size16 are now functions that resize the body text to 12, 14, and 16 pixels, respectively. You can attach them to buttons (in this case hyperlinks) as demonstrated in the following code example.

document.getElementById('size-12').onclick = size12
document.getElementById('size-14').onclick = size14
document.getElementById('size-16').onclick = size16
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>

Partial application and currying

See this answer for more detail.

References

Published 29 May 2020

Read more

 — Angular - Using Visitor design pattern with Typescript
 — Front end editorial style guide
 — Jekyll dark theme (minimal-mistake)
 — Understand and prevent the most common memory leaks in Angular application - Subscription unsubscribe
 — The different between [value] and [ngValue] when passing to select option

Follow @trungvose on Twitter for more!