DEV Community

loading...
Cover image for Nail your interview by learning Closure (backpack analogy)!

Nail your interview by learning Closure (backpack analogy)!

paulryan7 profile image Paul Ryan ・3 min read

'Can you explain Closure?'

Be prepared to hear this in almost all technical JavaScript interviews, it is one of the core questions they ask you in order to see how well you know JavaScript. You probably use closure daily when writing JavaScript but the majority of the time this is unknown to you.

To get into closure, let's look at a regular function:

     function helloWorld() {
          return "hello world"
     }

     const myFunction = helloWorld;
     myFunction()

This may not be the most inspirational code but if we delve a little bit deeper there is actually quite a bit going on.

     // add the label helloWorld into our global memory with the value of the function
     function helloWorld() {
          return "hello world"
     }
     // now add the label myFunction into our global memory 
     // with the value of the helloWorld label
     const myFunction = helloWorld;
     // call myFunction which will call the helloWorld function and create a new 
    //  execution context for helloWorld which will end when the return statement is met
     myFunction()

If you do not know what an execution context is then head here where I go in-depth.

The most important thing to note is that when we call a function, we create a new execution context for that function which we push onto the call stack then when we meet a return or the last } we pop if from the call stack.

Take the example below where the addOne function is removed from the call stack when it hits a return statement.

Call Stack Example

With an understanding of the call stack & execution context in place, we can now start with closure.

Let's take the classic counter example.

     function outer() {
       let counter = 0;
       function incrementCounter() {
         return counter++;
       }

       return incrementCounter;
     }

     const myCoolFunction = outer();
     console.log(myCoolFunction()) // 0
     console.log(myCoolFunction()) // 1
     console.log(myCoolFunction()) // 2
     console.log(myCoolFunction()) // 3

This kinda breaks what we were saying above, how is the counter value being persisted on each function call? We create a new execution context for each call so should this value not be essentially reset on each function call?

The magic is happening on this line:

const myCoolFunction = outer();

myCoolFunction is essentially getting two values here - the incrementCounter function and also the counter variable.

Just imagine that the incrementCounter function has a backpack with the values around it, so myCoolFunction is assigned the incrementCounter function and also it's backpack (thank you Will Sentence for this analogy).

Here is a beautiful image of that:
Backpack Image

There are few different names rather than backpack which sound a lot more fancy which are:

  • Persistent Lexical Scope Referenced Data (rolls off the tongue?)
  • Closed Over 'Variable Environment'

The above definitions will make you sound super smart in an interview, but for understanding closure just think of the backpack!

To go further in-depth with closure, here is a great article that also uses the backpack analogy.

Conclusion

Any questions on the above, feel free to contact me on my socials! ❣️

💂‍♂️ Insta 👀 Twitter 💬 Github 💭 LinkedIn 💥 Youtube 📭 Website

Discussion (2)

pic
Editor guide
Collapse
aakatev profile image
Artem • Edited

Great example, and detailed explanation! Glad to see JS developers using closures, and explaining the concept to others!

Collapse
paulryan7 profile image
Paul Ryan Author

Thanks very much Artem