Understand JavaScript: Closures and Prototypal Inheritance

Photo by Darryl Low on Unsplash

Understand JavaScript: Closures and Prototypal Inheritance

Closures

image.png

Credit : Edward Huang

Closures and Prototypal Inheritance are one of the two pillars of JavaScript. Closures are basically the combination of functions and the lexical environment or scope.

A closure is a combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). Source: (MDN)

Scope simply defines the area where functions and variables are accessible. Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. Functions are first-class objects in JavaScript meaning they are an entity that supports all other properties inherent to other entities such as being assigned a variable, passed around as a function argument, or returned from a function. Closures allow a function to access variables from an enclosing scope or environment even after it leaves the scope in which it was declared. Let’s look at an example below.

function a () { // Declare the first function a
 let grandpa = 'grandpa' //a variable that holds a string grandpa
 return function b () { //Return another function in a function(High order function)
  let father = 'father' // a variable that holds a string grandpa
   return function c () { //Return another function in a function(High order function)
    let son = 'son'
      return `${grandpa}, ${father}, ${son}` // A template string that returns a string
   }
  }
}
//Let's call each of the functions above
a(); //Returns function b()
a()(); // Returns function c()
a()()(); // Returns grandpa,father,son

The result of the code above is :

image.png When the function a () gets called **first it gets popped onto the stack and we create a variable environment that contains the variable grandpa. Let us visualize this concept below.

Assuming we have a box called closures box. When the first function is called and popped off the stack the variable stored is moved into the box closure box

image.png

In JavaScript, we have a memory heap which is simply where memory is allocated, and whenever a variable is no longer needed it gets garbage collected but in this example, the variable grandpa is not removed by the garbage collector because it is being referenced by something which in this case is function c().

The next b() function gets called and added onto the stack and once it gets popped off the stack the father gets placed into the special closure box since it is being referenced by function c().

image.png Now function c () gets popped onto the stack, It’s a variable environment or scope that only has the variable son but doesn’t have father and grandpa in it. When we try to return the function, the JavaScript engine will look into the special closure box and allow the function to return the variables grandpa and father.

Let’s look at another example:

Let’s make use of an example with a Web API setTimeOut

    // Second Example
function returnInFiveSeconds () {
  const returnOnTime = 'Hi, I am there now';
  setTimeout(function () { 
   console.log(returnOnTime);
   }, 5000);
}
returnInFiveSeconds();

We have a function in setTimeout and if we can remember setTimeout gets sent to the Web API to start a timer in our case 5 seconds and when the timer expires it get sent to the Callback Queue where it will wait until our Call Stack is empty and returnInFiveSeconds() has being popped off the stack, the Event Loop will take the setTimeout to the Call Stack and run the console.log(returnOnTime). Technically the variable returnOnTime should have being popped off the stack before we got to the setTimeout method but because of closures the functions was still able to access the variable even after it was popped off the stack.

Closures and Encapsulation

Encapsulation describes the idea of bundling data and methods that work on that data within one unit.

Encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components. Source: (Wikipedia).

We can use closure to hide and store data in a separate scope and use it only when deem fit.

Let’s write an example with some code.

const makeABombButton = () => {
  let timeWithoutDestruction = 0;
  const passTime = () => timeWithoutDestruction++;
  const totalPeaceTime = () => timeWithoutDestruction;
  const launch = () => {
    timeWithoutDestruction = -1;
    return 'bomb goes boooommmmmmmm';
  }

  setInterval(passTime, 1000);
  return {
     totalPeaceTime: totalPeaceTime

 }
}

const bombGoesOff = makeABombButton();
bombGoesOff.totalPeaceTime()
bombGoesOff.launch(); // THIS WON'T RUN AT ALL

If we run this in the dev tools we will get;

image.png

image.png

totalPeaceTime() is accessible as it is contained in the object returned while launch() isn’t as it is properly encapsulated. This is made possible with closures and encapsulation and can be used in many real life use cases where you don’t want users to have access to some functions or properties in your API or Code.

Prototypal Inheritance

What is Prototypal Inheritance

JavaScript is an protoypal-based, Object Oriented Programming. After the ES6 updates, JavaScript allowed for “prototypal inheritance”, meaning that objects and methods can be shared, extended, and copied.

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object. Source: (GeekforGeeks.org)

image.png

Credit: (GeekforGeeks.org)

In JavaScript, everything is an object. We use javascript prototype to add new properties and methods to an existing object constructor. Prototypical inheritance allows us to reuse the properties or methods from one JavaScript object to another through a reference pointer function.

All JavaScript objects inherit properties and methods from a prototype:

  • Date object inherit from Date.prototype
  • Array object inherit from **Array.prototype**
  • `Personsobject inherit from **Person.prototype`**

The Object.prototype is on top of the prototype chain and the rest all inherit from Object.prototype chain

image.png__proto__ is another keyword that can help us determine the parent/prototype of any object(even array or function) in javascript.

If we run array.__proto__ on our chrome dev tools. We can see all the properties of an array.

image.png

Let’s proceed to work with some examples

Example 1

let dragon = {
  name: 'Tanya',
  fire: true,
  fight() {
    return 5
  },
  sing() {
    if (this.fire) {
      return `I am ${this.name}, the breather of fire`
    }
  }
}

let lizard = {
  name: 'Kiki',
  fight() {
    return 1
  }
}

lizard.__proto__ = dragon;
console.log(dragon.isPrototypeOf(lizard)); // true
console.log(lizard.fire) // true
console.log(lizard.sing()) // I am Kiki, the breather of fire
const lizardFire = dragon.sing.bind(lizard)
console.log(dragon.hasOwnProperty(name)) // true
console.log(lizardFire()) // I am Kiki, the breather of fire
  • Lets make an object dragon with different function and properties and another object lizard with the same properties.
  • We have the isPrototypeof method that checks if an object exists in another object's prototype chain.
  • The bind() method creates a new function that when called as it’s this set to a provided value.
  • The hasOwnProperty()method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).

Example 2

const car = {
 name: 'Toyota',
 make: 'Camry',
 year: 2013,
}
const owner = {
 firstName: 'Teslim',
 lastName: 'Odumuyiwa',
}

car.__proto__ = owner;
console.log(owner.__proto__) // we receive the owner object
console.log(owner.__proto__.__proto__) // we receive the base constructor object
console.log(owner.__proto__.__proto__.__proto__) // we get null

The output is :

image.png

  • __proto__ returns the parent object of our current object that it inherits its properties from.
  • But if we further access the __proto__ property of their outputs then we get the constructor object that is the base unit of arrays, functions, objects etc in JavaScript.
  • We cannot go any further back than the Object property in the prototypal chain. Behind that we only receive null.

Wrapping Up

Closures and Prototypal Inheritance are two important pillars to learn before diving into Object-Oriented Programming and Functional Programming. Closures control what is and what isn’t a scope in a particular function and Prototypal Inheritance is commonly used in web frameworks to help allow the sharing of common behavior and state among familiar components

Further Reading:

Closures - MDN

Inheritance and the prototype chain - MDN

Understanding and Using Prototypical Inheritance in JavaScript - Educative.io