JavaScript Super Powers – Prototypal Inheritance

Inheritance is when one object gets access to the properties and methods of another object. the classical inheritance is very verbose but the Prototypal inheritance is simple, flexible, extensible, and easy to understand. both ways are not perfect but prototypal inheritance can be very powerful.

An object gets access to the properties and methods of another object through the prototype chain. arrays and functions for example are objects which are derived from the base object. the base object is the object that everything in Javascript gets created from.

The “__proto__” Property

When we create an array and print the property __proto__, we will see an array with all the array methods that we can use on the created array:


const array = [];
console.log(array.__proto__);  // an array with methods like concat, push pop...

When we created this array, beyond the scene the array was created from the array constructor. by doing __proto__ it went up the prototype chain to this array.

We can go up the chain further and see the base object. we can see it has methods too which means that anything that is a decedent of the base object gets access to these methods:


const array = [];
console.log(array.__proto__.__proto__);  // an object (the base object) with methods like toString, hasOwnProperty, isPrototypeOf, propertyIsEnumerable...

console.log(array.toString)  // access to the base object methods (result: "")

When we create a function and print the property __proto__, we will see the base function where all the functions are created from:


myFunction() {};
console.log(myFunction.__proto__); // base function
console.log(myFunction.__proto__.__proto__);  // an object (the base object) with methods like toString, hasOwnProperty, isPrototypeOf, propertyIsEnumerable...

console.log(myFunction.toString)  // access to the base object methods (result: function a() {})

When we create an object and print the property __proto__, we will see the base object:


const myObject = {};
console.log(myObject .__proto__); // an object (the base object) with methods like toString, hasOwnProperty, isPrototypeOf, propertyIsEnumerable...
console.log(myObject.__proto__.__proto__);  // null (top chain)

console.log(myObject.toString)  // access to the base object methods (result: function a() {})

To make our own prototypes, we could take one object and assign to its __proto__ property another object to derive from but we should never do this. we should never use the __proto__. it’s bad for performance (mess up the JavaScript compiler) and there are different ways to create inheritance:


// Never Do This!
const animal {
  ...
};

const dog {
  ...
};
dog.__proto__ = animal;

dog.isPrototypeOf(animal);  // true

The “prototype” Property

The above image describes how the prototypal inheritance works. the __proto__ is a pointer to up the chain prototype object.

For example, the property __proto__ of a function points to the prototype of the native function which the function was created from. in the example below you can see that they are equal:


function myFunction() {}

myFunction.__proto__ === Function.prototype // true (the __proto__ of the created function, points to the base function prototype)

console.log(myFunction.hasOwnProperty('apply'));  // false (this propert exists in the base function)
console.log(myFunction.__proto__.hasOwnProperty('apply'));  // true
console.log(Function.prototype.hasOwnProperty('apply'));  // true

Let’s see how we can create our own prototypes without using the __proto_ property. we can use the “Object.create” to create a prototype chain:


const animal = {
  live: true
}

const dog = Object.create(animal);
dog.age = 12;

console.log(dog.age);  // 12
console.log(dog.live);  // true
console.log(animal.isPrototypeOf(dog));  // true

Only functions have the prototype property. when we create a function which is special type of object, it has a __proto__ that links up to the prototype and it has a prototype but its empty because when we creat a function, we don’t have a use for the prototype inside it:


function myFunction() {}

console.log(myFunction.prototype);  // empty prototype

Prototypes, although they are a property on all functions, the only time we use prototypes is when we use constructor functions. constructor function usually start we a capital letter and they contain the actual blueprint or prototype that we use.

If we will print the prototype of the base object (Object), we will see that it’s not empty. turns out that the type of the base Object (Object) is “function” since it has prototype, more specifically its a constructor, an object constructor.


console.log(Object.prototype);  // an object (the base object) with methods like 

typeof Object // function
typeof {} // object

so when we create an object , for example with the curly braces like above, beyond the scenes JavaScript creates this object by using the Object constructor.

Summarize

Every function has a prototype property and it references to an object used to attach properties that will be inherited by objects further down the prototype chain. the last object in that chain is the Object.prototype.

Remember this, Object is a function because it has a prototype and the Object.prototype is the base object. the Object.prototype is the last object in the chain (from the top) that we can look up for properties on, before we point to null.

Everything in JavaScript is an object, they all inherit through the prototype chain from the base object.

By using prototypes we avoid repeating ourselves, we avoid adding the same code over and over and being inefficient with our memory and we can create interesting programming paradigms with them.