WTH is prototypal inheritance ????

Photo by Clément H on Unsplash

Every javascript developer in his learning cycle find it difficult to wrap his head around this prototypal inheritance. Inheritance in javascript is unique, it is totally different from what we see in the other languages like Java or Python. In the languages like, Java and C++, there is a concept of classes while Javascript doesn’t have any classes like Java(Yeah, ES6 provides us with classes but that’s not same, it is just a syntactic sugar).

Inheritance in javascript is a big topic, so we need to go through some basic concepts, like step by step. These are the 4 main components:-

  1. Constructors
  2. Prototype
  3. Object.create()
  4. Prototype chain

In this article, I would like to go through the first two topics and our main motive would be to understand them in and out, before jumping to the other two. A better understanding of these topics is necessary for understanding inheritance.Let’s begin,

Constructor

Constructor helps us to construct and initialise objects in javascript. Simple?Let’s see how.

//Example of a Constructor
const Ball = function(size){
this.size = size;
this.getSize = function(){
console.log(this.size);
}
};
  1. The above constructor is the simplest type of constructor.
  2. Constructor are kinda like javascript functions that will take a object and attach property(here size,getSize) to it.
  3. A constructor first letter should be an uppercase(not a thumb rule but it is preferred).
//Complete code for object creation with constructor
const Ball = function(size){
this.size = size;
this.getSize = function(){
console.log(this.size);
}
};
let football = new Ball('big');
console.log(football.getSize()); //big

Let’s see what is happening in the above code.

  1. We create a constructor ‘Ball’ which has the property of size and getSize.
  2. We, then created the instance of the Ball called football using the new keyword.
  3. new is the key here. new creates an empty object and equal it to football instance, and then passes this empty object(football instance) to the constructor function and attaches itself to this keyword.
  4. In short, new does this, Ball.apply(football,size)

Prototype

Okay, so now we know constructors, let’s see prototypes. Constructor and functions in javascript are objects. And objects have properties, right?. So, constructors should also have properties and one such property is prototype.

console.dir(Ball);
//ƒ Ball(size)
arguments: null
caller: null
length: 1
name: "Ball"
prototype:
constructor: ƒ (size)
__proto__: Object
__proto__: ƒ ()
[[FunctionLocation]]: (index):67
[[Scopes]]: Scopes[1]

console.dir allows me to look at an object at a much more detail. In the above code, we could see a property attached to Ball constructor called prototype. And that prototype has property called __proto__, and so does the constructor. WTH are these????

  1. __proto__ — Every object in javascript has this property. It refers to the creator of that object. And when I say every object, I literally mean it. Have a doubt? Check it.
console.dir({})
/* Object
__proto__: Object
*/

This __proto__ points to its creator(i.e the master object, Object) and the constructor __proto__ also points to the Object.

2. prototype — Just think of it has a property on a constructor, on which we can attach some methods(for now).

const Ball = function(size){
this.size = size;
};
Ball.prototype.getSize = function(){
console.log(this.size);
}
let football = new Ball('big');
let tennisball = new Ball('small');
console.log(football.getSize()); //big
console.log(tennisball.getSize()); //small

In the above code, we attach the getSize method on the Ball constructor prototype, and all the instances have access to the constructor prototype and the methods attached to it.
Okay, how?

console.dir(football);
//Ball
size : "big",
__proto__ :
getSize:ƒ ()
constructor: ƒ (size)
__proto__: Object

Let’s try to get what’s going on,

  1. We have the size property as expected, on the football instance.
  2. __proto__ should point to its creator, and the creator of the football instance is the Ball constructor.
  3. You might be thinking what is getSize doing on __proto__ as we attached it to the prototype, What actually happens is, that the new keyword creates a reference of getSize on the __proto__.If you expand the constructor function in the console you will find that the prototype has getSize attached to it.
//constructor:ƒ (size)
arguments:null
caller:null
length:1
name:"Ball"
prototype:
getSize:ƒ ()
constructor:ƒ (size)
__proto__:Object

4. See, there is your getSize on the prototype. And __proto__ on the prototype of constructor refers to the creator(Master Object).

One last thing in this topic, I would like to answer is, What is the use of prototype??? Here, we have two instances so you wouldn’t get the reason, but suppose we have more than 100 instances and each instance have some methods attached on themselves, that will make your application run slower.

So we attach the methods to constructor’s prototype and try to keep minimum properties and methods on these instances for a better run time. Hundreds of instances with various methods attached to them, is not a good approach.

That’s why we attach all the methods on the prototype and every instance that needs to access the method will look for the method in the constructor function and if there it does not find the method, then it looks for it in the __proto__ and so on.

I hope you guys are able to wrap your head around these two concepts as these two topics are the basic foundation of the prototypal inheritance.

In next article, we will discuss about the ‘Object.create’ and ‘prototype chain’ and how inheritance works when all these four components are put together.