Prototypal Inheritance 2: The eternal battle between classical and prototypal inheritance in javascript

Why is classical inheritance not the best choise when it comes to Javascript?
Why is prototypal inheritance better then classical one?
Why many developers used classical inheritance style in javascript?
We will answer to some of these questions while understanding the misconception behind prototypal inheritance.

[ The content of this article is my take home from the great book of Kyle Simpson this & Object Prototypes of the series "You don't know JS", i really recommend to read it in order to fully grab these concepts! ]


Here you can find the other posts of this series:
Prototypal Inheritance 1
Prototypal Inheritance 3


In our previous post we finally clarify some of the most used terms around prototypal inheritance.
We learnt that Object-oriented programming is nothing more of programming paradigm which means is not restricted to any programming languages in particular nor must necessarly used together with some kind of inheritance.
With that in mind we defined what is Classical Inheritance generally speaking, not just related to javascript.
We can now say that Classical inheritance is when a Object or a Class is based on another class (if you are not sure what a Class is, I suggest you to read Prototypal Ihneritance 1).
And most important of all, we now know that classical inheritance is done by copying the Class behaviour!
We need to stick this in our mind to understand what prototypal inheritance is and how it work.

[[Prototype]]

If classical-inheritance is class-based inheritance, prototypal-inheritance probably is prototype-based inheritance.
But what is this prototype?
[[Prototype]] is an internal property of Object which is simply a reference to another Object.
When we create a new object in javascript, a prototype is set on it with null value (in almost all the cases.)

Why is this prototype created? For which purpose?
We should think about [[Prototype]] as connection, a link between two objects.
Let's consider:

var myObj = {  
  a: 2
}

var anotherObject = Object.create(myObj);

anotherObject.a; //2  

anotherObject is now [[Prototype]] connected with myObj.
But what happen when we call anotherObject.a?
We are looking for a property that doesn't exist on anotherObject and isn't found so the default [[Get]] operation keep looksup for this property following the [[Prototype]] link-chain.
Looksup keep going until property is found or chain ends.
If no match is found, the result of [[Get]] is undefined.

When the [[Prototype]] chain end?
All the normal object in javascript, descend from Object.prototype.
This is an object which includes many utilities used in javascript like:

  • .toString()
  • .valueOf()
  • .hasOwnProperty()
  • .isPrototypeOf()

So the end of the [[Prototype]] chain for normal objects is Object.prototype.

Prototypal Inheritance

I guess by now you already have more or less an idea of what prototypal inheritance is:
Is an inheritance based on prototypal-linking.

But what is so different between class-based inheritance and prototypal-inheritance?
We said previously that when we create an instance of a Class, this Class get literally copy.
Is like a stamp, where many copies could be made from it.
Initialize a Class means copy the "behaviour" from the Class.

When it comes to prototypal:

  • The "inheritance" happen between two objects and not between two classes or a class and an object.

  • The objects get linked together, but there is no copy operation involved anywhere!

The last concept is very important, it show us how the behaviour of the two inheritance style is deeply different: Classical and inheritance in general work copying DOWN to the chain, instead with prototype in Javascript the objects looksup to the chain.

Here we can see the same picture made for classical inheritance in the previous post, but now done for prototypal linking:

At this point we are able to replay to the question:
Why is so wrong to think about Class in javascript?
And why it said that Class doesn't exist in javascript?

Outside the fact that Class doesn't exist in the nature of Javascript language, when developers say Class doesn't exist in particular it means that they can't even be emulated; we previously said that Class are like instruction and don't work alone.
They need to be inherited or initiate to be used.
In Javascript we can try to emulate a Class typical behaviour but the only element we have to emulate it, is the Object.
But objects are mutable and can be used straight away. They don't need to be initiate, they can be just used like that, if we want.
On top of that, we just state that inheritance imply copy operation and prototypal instead link objects together, where one object can delegate property or function access to another object.
If we build our code with the idea that our objects are going to copy the Class/Object behaviour, we can write our code in the style we like more and make it look like a class-base but, in javascript, objects will still get linked together and delegation mechanism will take place (not copy)
which will lead to weird behaviour from time to time and will make some easy operations more difficult and tricky then normal class-based languages.

Class behaviour emulation

Then why so many developers try to emulate class behavour in javascript for so many years?
There are some part of the javascript language that could look like a class-base language.
The new keyword for example.
When new is used a new object get create but actually there is more, this is what actually happen when new is used:
1. brand new object is create
2. The newly constructed object is linked via [[Prototype]]
3. The newly constructed object is set as this binding for that function call
4. The new invoked function, will automatically return the new created object.

This means that using new keyword is just an indirect and confusing way to do what Object.create() does.
Also using new there is a side-effect.
Basically when newObject get create with new, it use a myObject constructor call to do so, this means that if myObject has any behaviour like changing state or modifing other objects, those operations will execute at the linking time.
Instead they should be executed just when newObject is created.

The best way to create a new object is using Object.create().
Unfortuantely it has a small downside too:
It create a new Object and throw the old one away. Instead it would be cool to recycle this Object and just modify it.
With ES6 this is finally possible, using:
Object.setPrototypeOf(...)

// before ES6
newObject.prototype = Object.create(myObject.prototype)

// ES6
Object.setPrototypeOf(newObject.prototype, myObject.prototype)  

Another Javascript's behaviour contribute to bring lot of confusion to the Class or not Class question.
When an Object is created it get automatically a public, non-enumerable property attach to its prototype, called constructor and it refere to the Object is associated with.

function Foo(){}  
Foo.prototype.constructor === Foo; //true  
var bar = new Foo();  
bar.constructor === Foo; //true  

The newly created Object bar has a constructor which point to Foo.
It basically look like we are executing a constructor method of a class.

For this behaviour and for the strong mental precedent that the word "inheritance" has, developers try to fit classical inheritance code style into non class-based Javascript language.

Prototypal vs classical inheritance

Why often we hear people say that prototypal-inheritance is better then classical one?
Thanks to the prototypal linking and to Object.create() we can create new objects linked to each others with all the power of Prototypal mechanism (looksup for instance) but without the unnecessary complication of classes.
Complicatons like:

  • Tight coupling: parent and child have intimate relation.
  • Architecture: tight coupling lead to fragile architecture
  • Multiple inheritance: Is complicated to inherite from more then one parent but is something often need to do.

Instead for prototypal inheritance all the opposite is true: no narrow relation between two objects, which lead to easier to modify architecture and inheriting from different parents is easy. We could easily combine property from any objects source.

Code example of typical prototypal-style in javascript:

functio Foo(name){  
  this.name = name;
}

Foo.prototype.myName = function() {  
  return this.name;
}

function Bar(name, label){  
  Foo.call(this, name);
  this.label = label;
}

Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.mylabel = function(){  
  return this.label;
}

var a = new Bar('a', 'obj a');  
a.myName(); // a  
a.myLabel(); // obj a  

(we will see in the next post how to improve it)

Conclusion

we can now say that the difference between classical inheritance and prototypal inheritance are the elements they use, one use Class and other Object, and how their mechanism works: the first one copy the Class behaviour instead the second one link objects with a [[Prototype]].
After this was easier to understand why isn't so smart to write Javascript in class-oriented way but we also underline why so many developers get confuse and are lead to think that Javascript can also be used or at least emulate a class-based language.
We discover alternative method to "inherite" a new object so we don't have to use new keyword and in the end we also discuss briefly what are the cons that lead developers think prototypal "inheritance" is better then classical one.

As you might notice, every time i talk about prototypal "inheritance" I wrap the word inheritance in quotes.
This is because, as K. Simpson say, it doesn't make so much sense to call inheritance the prototypal one, since inheritance means copy and here there is no copy operation at all.
Is a term given because it was easier to identify but it actually just crete more confusion.
In the next and last post we will see how Kyle Simpson find a solution to this problem.