#### JavaScript Prototypes and Prototype Chain

##### July 20, 2018
js prototypes inheritance prototype chain objects

We all know JS has objects, for example:

var obj = { name: 'obj' };


and we can access/create/update/delete properties on object obj. But before doing any further operations on it, we can notice that obj already has some properties like valueOf, toString, etc.that we’ve never assigned. Now we have to understand how prototypal inheritance works.

## Function as a constructor

In JavaScript, there’s really no difference between a “regular” function and a constructor function. They’re actually all the same. But as a convention, functions that are meant to be used as constructors are generally capitalized.

Let’s create a constructor function called Cat:

function Cat (breed){
this.breed = breed;
}

typeof Cat.prototype; // "object"


Fun fact here, all functions in JS are also objects, which means that they can have properties. And as it so happens, all functions have a property called prototype, which is also an object.

To make an instance of Cat, we can use the new keyword to “construct” an object from this constructor function:

let kitty = new Cat ('Scottish fold');
kitty.breed; // "Scottish fold"


## Prototypal inheritance

As a cat person, I just couldn’t resist the soothing sound of “meow”, now that we have an object kitty, how can we make it “meow” just like any other cat does? Remember that all functions have a prototype property right? Actually, the object kitty and any other object constructed from Cat will gain indirect access to Cat.prototype. By placing meow on Cat.prototype, we made it available to all instances of Cat.

Cat.prototype.meow = function(){
console.log("Meowwww");
}
kitty.meow(); // "Meowwww"


Even though the object kitty constructed from Cat does not have a meow property on itself, it was able to access Cat.prototype and thus invoke Cat.prototype.meow with this being implicitly set to kitty, which results in “Meowwww” being logged to the console.

This form of code reuse is known as prototypal inheritance, since an instance has an “invisible link” back to their parent object.

## Prototype chain

The “invisible link” mentioned above is referred to as the prototype chain. What actually happens when I write kitty.meow() is this:

1. The JS engine looks for a property called meow on our kitty object.

2. It doesn’t find one, it looks “up the prototype chain” to kitty’s parent, which is Cat.prototype.

3. It finds Cat.prototype.meow, and calls it with this bound to kitty.

The traversal algorithm consults the object’s prototype when it cannot find the desired property on the object. If it finds the property on the prototype, the traversal stops. Otherwise, it will consult the prototype of the prototype, and so on, until it finds the property or it reaches the end of the prototype chain.

• __proto__ and Object.getPrototypeOf

Every object has a __proto__ property on itself, which is also an object. According to the description on MDN:

The __proto__ getter function exposes the value of the internal [[Prototype]] of an object.

You can understand this by saying xxx.__proto__ equals to xxx’s prototype. An instance object of a prototype shares some characteristics of its prototype.

For an object created using the new FunctionName constructor function, __proto__ points to the prototype property of its constructor function; And for an object created using an object literal, this value is Object.prototype.

const constructedObject = new FunctionName();
const objectLiteral = {};
constructedObject.__proto__ === FunctionName.prototype; // true
objectLiteral.__proto__ === Object.prototype; // true


Besides __proto__, we can also use Object.getPrototypeOf to check an object’s entire prototype chain.

const constructedObject = new FunctionName();
const objectLiteral = {};
Object.getPrototypeOf(constructedObject) === FunctionName.prototype; // true
Object.getPrototypeOf(objectLiteral) === Object.prototype; // true


In our cat example, that means:

kitty.__proto__ === Cat.prototype; // true
Object.getPrototypeOf(kitty) === Cat.prototype; // true


The lines above tell us that the prototype of kitty is Cat.prototype. Therefore, if JS cannot find the desired property on kitty, it will check Cat.prototype.

• What about Cat.prototype’s prototype?

kitty’s prototype chain starts with Cat.prototype, if JS is still unable to find the desired property on Cat.prototype, it will look at the prototype of Cat.prototype, which is Object.prototype.

FunctionName.prototype.__proto__ === Object.prototype; // true
Object.getPrototypeOf(FunctionName.prototype) === Object.prototype; // true

// our cat example
Cat.prototype.__proto__ === Object.prototype; // true
Object.getPrototypeOf(Cat.prototype) === Object.prototype; // true


That’s because Cat.prototype, which is also an object, was constructed from the built-in Object constructor (whether or not this is the case is an implementation detail).

• And deeper, Object.prototype?

Is Object.prototype the final prototype in kitty’s prototype chain? Yes, because Object.prototype does not have a prototype (it is null).

Object.prototype.__proto__ === null; //true;
Object.getPrototypeOf(Object.prototype) === null; // true


Even though Object.prototype is an object, its prototype is not Object.prototype, otherwise we will have an infinite prototype chain.

The fact that nearly all objects have Object.prototype at the end of their prototype chains is of practical significance because they will have access to common utilities offered by Object.prototype such as toString and valueOf, which answered our first question at the beginning of this post.

## A function’s prototype

Going back to our constructor function Cat, does Cat.prototype refer to the function Cat’s prototype?

Nope!

Object.getPrototypeOf(Cat) !== Cat.prototype; // true


The actual prototype of Cat is Function.prototype.

Object.getPrototypeOf(FunctionName) === Function.prototype; // true
FunctionName.__proto__ === Function.prototype; // true

// Our cat example
Object.getPrototypeOf(Cat) === Function.prototype; // true
Cat.__proto__ === Function.prototype; // true


This is bacause very function in JavaScript is a Function object, and thus it has a prototype of Function.prototype.

Function.prototype offers common utilities like call, bind and apply which can be accessed from Cat and other functions.

And similarly, the prototype of Function.prototype is also Object.prototype, since after all, the Function object is still an Object instance.

Resources:

Prototypal Inheritance in JavaScript

A Definitive Guide to JavaScript Prototypes

MDN