Closures = Your favourite Burger

Closures = Your favourite Burger

A simple explanation to the make or break question in JS.

I remember bombing my first Javascript interview with style - I knew I was out of the gate when I couldn't explain what a Closure was. I absolutely knew what it was - but somehow was unable to put into words.

So, what is a Closure?

Closure

In my mind Closure = Burger - Yup - thats it and nothing else.

Don't believe me - read ahead and you will start believing in burgers - I mean Closures :)

Burger Preparation

What all is needed to make a burger in the first place.

  • Bread (Wheat or White)
  • Patty (Veg or Non-Veg)
  • Side kicks (Onions, Ketchup, Mayo etc)

With that in mind - let's create our finger-licking in-house Closure aka burger.

let sideKicks = ['onions', 'ketchup', 'tomato slices', 'mayo'];

function burger(breadType) {
  function patty(pattyType) {
    return (
      breadType +
      ' bread, with ' +
      pattyType +
      ' patty,' +
      ' sprinkled with ' +
      sideKicks.toString().replaceAll(',', ' - ')
    );
  }
  return patty;
}

f patty has access to the global variables (sideKicks) and its own variable(pattyType).

Including this - It has access to the breadType that we pass to f burger - This exact line is what a closure is - It closes over its surrounding variables also known as lexical environment.

Trying to get my six packs on - so today's burgers will be a Wheat Chicken burger:

  • Bread - Wheat
  • Patty - Chicken
  • Side kicks - onions, ketchup, tomato slices, mayo

With that, if we call the function:

var patty = burger('Wheat');
var burgerWithPatty = patty('Chicken');

console.log(burgerWithPatty);

//Output
Wheat bread, with Chicken patty, sprinkled with 
onions - ketchup - tomato slices - mayo

That is one delicious burger. Yummmmm.

To get to the meat of it, do a console.dir on f burger and f patty .

console.dir(burger);
console.dir(patty);

We can see here fburger has in its scope:

  • ingrediants
  • global window object
f burger(breadType)
arguments: null
caller: null
length: 1
name: "burger"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: app.js:3
[[Scopes]]: Scopes[2]
0: Script {sideKicks: Array(4)}
1: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

Whereas fpatty has in its scope:

  • Closure (burger) {breadType: "Wheat"}
  • ingrediants
  • global window object
f patty(pattyType)
arguments: null
caller: null
length: 1
name: "patty"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: app.js:4
[[Scopes]]: Scopes[3]
0: Closure (burger) {breadType: "Wheat"}
1: Script {sideKicks: Array(4)}
2: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

​

Well if you are still hungry - You could just do

var anotherBurgerWithPatty = patty('Veg');

In short - Closure is nothing but a patty which knows which type of bread is it enclosed by.

Next time somebody asks what a Closure is - counter question - which is their favourite burger?