DEV Community

Cover image for  You can't understand JavaScript without mastering Closure

You can't understand JavaScript without mastering Closure

Albert Hadacek
React / Node developer and Software Engineering student
・3 min read

Closure is one of the features of the language that many programmers struggle to wrap their heads around. Yet, it is one of the core building stones of JS and a frequent topic that appears in coding interviews. In this article, you will learn all about it.

What happens when you call a function?

To understand closure, we need to fully understand how a JavaScript program works. Our code is interpreted line by line. Variables are stored in the global memory and we have a single execution thread.

When the interpreter reaches a function invocation the function is placed on the call stack and a new execution context is created for the function - it has its local memory and thread of execution. Think of it as a mini-program. When the function returns, either explicitly (reaching a return statement) or implicitly (by default functions return undefined), the function leaves the call stack and its execution context is destroyed.

What the heck is Closure?

Imagine this piece of code.

let name = "John"

function greet() {
  const greeting = "Hi"

  function printHi() {
    console.log(greeting + ' ' + name)

name = "Jane"

greet() // "Hi Jane"

Enter fullscreen mode Exit fullscreen mode

Our inner function printHi has access to the local memory of its parent (greet) and the global memory. Notice, that we actually have access to the "fresh" data that is available during the call, not the declaration. That is how lexical scoping works in JavaScript.

But what would happen if we return a function instead of just calling it within the body of the outer function. Well, here the magic comes. A returned function from another function is not just a simple function definition, it is the definition plus the variables it has access to and needs to run stored in a backpack that comes with it.

What we just described is the mysterious closure. Formally, a closure is a when function remembers its lexical scope (the backpack) even when the function is called outside of that lexical scope.

function creator(num) {
  return function() {
    num = num * 2

const double = creator(5)
double() //10
double() //20

const double2 = creator(7)
double2() // 14
double2() //28

double() // 40

Enter fullscreen mode Exit fullscreen mode

As we can see in the snippet above, whenever we call double it updates the same piece of data (num from its parent function) that is stored in its backpack, which is technically the hidden [[scope]] property the function has.

If you are wondering why is it useful, check the examples below.

Module pattern

The closure allows us to protect or hide certain pieces of information. The backpack is a hidden property so we can't just access it and update it as we would do with a standard object literal. It is also important to mention, that we can return a set of functions stored on an object and they would all be closures.

In the snippet below we are taking advantage of the so-called IIFE (Immediately Invoked Function Expression) which allows us to eliminate the middle step of calling the outer function as we do it directly when assigning it.

const myModule  = (function(){
  const apiKey = "123456789"

  return {
    displayKey() {

myModule.displayKey() // "123456789"

Enter fullscreen mode Exit fullscreen mode

If we expose this module to another programmer, the API we prepared for him, does not allow him to change the key, he can only see it and there is no way he or she could change it other than rewriting it in the source code.

Basic caching and memoization

Imagine you would like to create a simple generator of IDs. To make sure you always return a number that is higher than the previous one, you can use closure. We will cache the value of the highest id in our current variable.

const newID = (function() {
  let current = 0
  return function() {
    return ++current

newID() // 1
newID() // 2

Enter fullscreen mode Exit fullscreen mode

This idea of keeping track of certain data might be extremely useful when we are doing expensive computations, we can store parts of the results in a cache and when we do a computation with a higher number, we can use the data from our cache as a base. This process is called memoization. A prime example of that would be working with factorials or Fibonacci sequences.

const factorialMemo = (function() {
  const cache = {}
  return function factorial(n) {
    if(n === 1 || n === 0) {
      return 1
    } else if (cache[n]) {
      return cache[n]
    } else {
      cache[n] = n * factorial(n-1)
      return cache[n]

factorialMemo(5) //120
// cache object looks like {'2': 2, '3' : 6, '4' : 24, '5' : 120}
factorialMemo(6) // 6 * cached 120 

Enter fullscreen mode Exit fullscreen mode

Discussion (11)

kabircse profile image
Kabir Hossain

There is no double function. So how is it works ?

double(); //10
double(); //20

danishsiraj profile image
Danish Siraj

The creator function is assigned to double here in this line

const double = creator(5)
double() //10

calling double is in essence calling the creator function.

albert_hadacek profile image
Albert Hadacek Author

Its calling what creator function returns not calling the creator ;)

albert_hadacek profile image
Albert Hadacek Author

There is, as the creator returns a function definition which you can call afterwards

aybasaran10 profile image
Ahmet Yusuf Başaran

Check twice bro ur gonna figure it out!

andrelomba86 profile image

Nice post, but 0! = 1 or am I wrong?

albert_hadacek profile image
Albert Hadacek Author • Edited

What do you refer to?

EDIT: I can see it now, corrected, thanks

jongmassey profile image
Jon Massey

Eh, in Javascript you can never be too sure ;)

umutakyol profile image

Forget it, if you need it, you learn it. It's not a big think, or hard to learn. But if youre goint to some interview, then learn it. Interviewers like this topic. :)

asaduzzaman69 profile image
Asaduzzaman Himel

Everyone post tutorial in here! can I ask the question a post?

shaijut profile image
Shaiju T

Yes you are welcome to ask questions related to this post. :)

Forem Open with the Forem app