DEV Community

Cover image for Javascript academy #2: Closures
CodeOz
CodeOz

Posted on

Javascript academy #2: Closures

Welcome to this new academy! In this I will NOT explain you javascript from scratch, the aim of this javascript academy is to explain you some concept in javascript that will help you to understand javascript engine!

Today I will teach you what is a Closure?

Short Definition

A Closure is a function that can access to variable outer its own scope.

πŸ€”...

Ok let's take an example!

let b = 5

function toto(a) { return a + b }
toto(1) // 6
Enter fullscreen mode Exit fullscreen mode

When the JS Engine will pass to the function, it will check for each variable if this variable is available in the current context, here only the variable a is available since it's the parameters.

But when it will check the b variable, it will check that this variable is not available in the function context! So it will check if this variable is available in the outer context!

This is called a Closure!

But the JS Engine need to make some tricks in order to keep the outer variable access in the function!

In fact JS Engine will store the outer variable (b) in the memory heap! So it keep a reference into this variable and when we will invoke the function, the variable will be available!

In fact this outer variable is store in an object name Lexical environment.

What is the Lexical environment ?

Lexical environment only exists β€œtheoretically”! It grant all thing that a function need to have in order to be invoked! It's composed in 2 parts:

  • Environment Record that will store local variable.

  • Reference to the outer variable used in this function.

Now let's look how JS Engine manage variable scope in function

const toto = 5 // declared in the global scope

function hello () = {
   let a = 35
   let toto = 45
   console.log(a + toto)
}

hello() // 80
Enter fullscreen mode Exit fullscreen mode

Why in the example above when we are calling console.log(a + toto) the value of toto is 45 and not 5?

When we will invoked a function, JS Engine will check if the variable is in the current context (Environment Record), in this case it will take this value, otherwise it will check if the variable exist in the outer context until reaching the Global Scope.

Another example to understand this behavior!

const toto = 'toto global | ' // declared in the global scope
const b = 'b global | '

function hello () {
   const a = 'a hello | '
   const toto = 'toto hello | '
   const c = 'c hello | '

   return function hey () {
      const c = 'c hey | '
      console.log(a + toto + b + c)
   }
}

hello()() // a hello | toto hello | b global | c hey |
Enter fullscreen mode Exit fullscreen mode

Do you see the logic know?

The purpose of Closure

It use more ressource, so why use closure?

Moreover we can create side effect!

let toto = 55

function change() {
   toto = 69
}

change()
console.log(toto) // 69
Enter fullscreen mode Exit fullscreen mode

But you can encapsulate data and create some secret & protected variable!

function hello() {
   let counter = 0
   return function () {
      counter++
      console.log(counter)
   }
}

const upCounter = hello()
upCounter() // 1
upCounter() // 2
upCounter() // 3
Enter fullscreen mode Exit fullscreen mode

Your variable is safe and you can only change it by the function return by hello!

Moreover, each instance of hello() has its own context!

const upCounter1 = hello()
const upCounter2 = hello()

upCounter1() // 1
upCounter1() // 2

upCounter2() // 1
Enter fullscreen mode Exit fullscreen mode

Quizz about Closure

const arrFuncs = []

for(var i = 0; i < 5; i++) {
  let toto = function () {
    return i
  }

  arrFuncs.push(toto)
}

console.log(i) // i is 5

arrFuncs.forEach(arrFunc => console.log(arrFunc())) // All logs
Enter fullscreen mode Exit fullscreen mode

Why it's logging 5 and not 0, 1, 2, 3, 4 ?!

Let understand this step by step!

for(var i = 0; i < 5; i++)
Enter fullscreen mode Exit fullscreen mode

equal to

var i
for(i = 0; i < 5; i++)
Enter fullscreen mode Exit fullscreen mode

Since we are using var, the variable i is hoisted to the global scope!

So when we are doing

  let toto = function () {
    return i
  }
Enter fullscreen mode Exit fullscreen mode

We are using toto function as Closure!

And as we know, closure used reference for outer variable(var i is an outer variable since it's declares on global scope)

So when we will execute each closure (during the forEach) we will get the variable value from the reference, and the current value at this point is 5!

So this is why we console log 5 five times!


I hope you like this reading!

🎁 You can get my new book Underrated skills in javascript, make the difference for FREE if you follow me on Twitter and send message to me 😁 and SAVE 19$ πŸ’΅πŸ’΅

Or get it HERE

πŸ‡«πŸ‡·πŸ₯– For french developper you can check my YoutubeChannel

🎁 MY NEWSLETTER

β˜•οΈ You can SUPPORT MY WORKS πŸ™

πŸƒβ€β™‚οΈ You can follow me on πŸ‘‡

πŸ•Š Twitter : https://twitter.com/code__oz

πŸ‘¨β€πŸ’» Github: https://github.com/Code-Oz

And you can mark πŸ”– this article!

Discussion (0)