Pseudoclasses and prototypal inheritance in JS
This is my third post in the series of “JS: Leave the classes to those other languages”. If you haven’t checked out the first two posts, you can read them on JS: Leave the classes to those other languages and JS Prototype chain mechanism.
Real classes (classical inheritance)
Before diving into pseudoclasses it is important to point out some characteristics of real classes (classes in Java, Ruby, etc).
In traditional languages:
- Classes are blueprints
- Objects (instances) are copies of all the characteristics described by classes
Here giamir
is an instance of Student
and when we send to it the message name
or school
, giamir
knows how to handle the message without asking or delegate to some other objects.
In JS this is not possible because JS doesn’t copy object properties (natively, by default).
Pseudoclasses (prototypal inheritance)
Prototypal inheritance is the most popular way to fake classes (work with pseudoclasses) in JS.
The following code implement a pseudoclass Person
and a pseudoclass Student
that “inherits” from Person
.
It’s also creating an “instance” of the pseudoclass Student
and assigned it to a variable giamir
.
Here is a mental map of the prototype chain generated by the code above.
We create a function Person
and a function Student
and we want to use them as constructors. Functions in JS automatically get a property called prototype
, which is just an empty object internally linked to Object.prototype
.
We use explicit pseudo-polymorphism to delegate between Student
and Person
constructors. We call the Person
constructor in the context of the new object we are creating using the Student
constructor.
Obviously we want the Student.prototype
object be able to use all the Person.prototype
methods. To do so we need to replace Student.prototype
with a new object that delegates to Person.prototype
instead of Object.prototype
. The easiest way to do that is using the ES5 Object.create()
method:
Once that the prototype chain is in place we can create a new object giamir
using the Student
function as a constructor:
Here giamir
is an object that delegates to Student.prototype
and when we send to it the message getSchool
for example, giamir
has to delegate the message to the object above it in the prototype chain and so on.
Inheritance or delegation?
The word “inheritance” has a very strong meaning with plenty of mental precedent. Merely adding “prototypal” in front to distinguish the actually nearly opposite behaviour in JS is inappropriate.
JS creates a link between two objects, where one object can essentially delegate property/function access to another object.
Delegation is a much more accurate term for JavaScript’s object-linking mechanism.
If you’re creating constructor functions and inheriting from them, you haven’t learned JavaScript. It doesn’t matter if you’ve been doing it since 1995. You’re failing to take advantage of JavaScript’s most powerful capabilities.
You’re working in the phony version of JavaScript that only exists to dress the language up like Java.
– Eric Elliott
We are ready to explore alternative patterns in JS to get rid of pseudoclasses and finally embrace the nature of the language.