Scope, hoisting, event loop: Closures

In JavaScript, when we call a function, all the variables available in the outer scope are made available inside the function as well.

Let me immediately give an example to clarify this concept.

Say we have a bark() arrow function:

const bark = dog => {
  const say = `${dog} barked!`
  console.log(say)
}

bark(`Roger`)

This logs to the console Roger barked!, as expected. No problem here, nothing new.

But.. what if we want to return a function whose job is to print say to the console?

Like this:

const bark = dog => {
  const say = `${dog} barked!`
  return () => console.log(say)
}

Now when we invoke bark('Roger') we don’t get that string printed to the console. Nothing is printed to the console.

But we get back a function, that we can call when we want, for example we can call it immediately:

const makeRogerBark = bark(`Roger`)

makeRogerBark()

As you can see, the state of the variable say is now linked to the function that’s returned from bark().

We can invoke bark() two times:

const makeRogerBark = bark(`Roger`)
const makeSydBark = bark(`Syd`)

makeRogerBark() //Roger barked!
makeSydBark() //Syd barked!

The scope of the inner function we returned from bark() also includes the scope of a parent function, and this is called closure.

Lessons in this unit:

0: Introduction
1: Global scope
2: Function scope
3: Block scope
4: Shadowing
5: Hoisting
6: ▶︎ Closures
7: An issue with `var` variables and loops
8: The event loop
Want to learn more? Check out our courses