A Verbal Diagram of Prototype Inheritance

In JavaScript, objects delegate to each other using prototypes instead of inheriting from classes as in many other languages. This topic has been the most difficult for me to absorb so far in my programming studies. I’m not much for visual learning, so all of the web diagrams of different colored boxes pointing in several directions at other boxes just boggled my brain further. I feel I have a good grasp of it at this point. To solidify my understanding further, I’m going to tell a story about these relationships…

We are in the global name space of our Chrome browser. A brand new Creature object is created. We can call it baby (or really, we can point the variable baby at a reference of the new Creature object). Even though we only see one object, baby’s rich family history actually goes a long way back. First off, its constructor is how it was made, Creature.

baby.constructor === Creature

Creature, as does every function, has a prototype property that points to its buddy object. This object has a constructor property that points back to Creature, undeniably linking them.

Creature.prototype.constructor === Creature

If Creature is used as a constructor, its buddy will step in and act as the prototype for any objects Creature creates. Being an object, baby has a dunder proto property, which points to its prototype, and having been constructed from Creature, this prototype is Creature’s buddy object.

baby.__proto__ === Creature.prototype

That’s it for the immediate family. Now, let’s look further up the family tree (or prototype chain). Where did Creature and its buddy, Creature.prototype, come from? Creature is a constructor function, which is really just a function, which is really just an object made from JavaScript’s built-in Function constructor. So,

Creature.constructor === Function

If Creature is actually an object, as we just said, then it must have a dunder proto property just like baby does. This points to Function’s buddy object, just like in the younger generation’s case.

Creature.__proto__ === Function.prototype

Creature’s buddy object wasn’t created by Creature but it was created because of Creature, and Creature is the constructor it works with, so it makes sense to me that its constructor property points to Creature. It is an object, too, so it must have a dunder proto property. In this case, having been constructed automatically alongside Creature, its prototype is JavaScript’s built-in Object prototype.

Creature.prototype.__proto__ === Object.prototype

Lastly, we’ll examine these built-in objects. Function and Object and their respective prototype buddy objects are linked to each other in the same way as we’ve seen in other generations.

Function.prototype.constructor === Function

Object.prototype.constructor === Object

Function’s prototype object was created automatically just like Creature’s prototype object, so it also delegates to Object.prototype.

Function.prototype.__proto__ === Object.prototype

Object is a function, so it was constructed from Function. Oddly, Function is also a function, so Function was constructed from itself. Things have to start somewhere, you know.

Object.constructor === Function.constructor === Function

As objects, both Object and Function have dunder proto properties which point to prototype object of their constructor.

Object.__proto__ === Function.__proto__ === Function.prototype

A couple more relationships will wrap this up. Function and Object’s prototype objects have dunder proto properties, too. Function’s prototype object has the built-in Object prototype as a prototype just like Creature’s prototype object did.

Function.prototype.__proto__ === Object.prototype

Object’s prototype object, on the other hand, cannot have itself as a prototype. Object’s prototype object just is. Before it, there was nothing….

Object.prototype.__proto__ === null

Now we know baby’s genealogy. It all sounds complicated, mostly because of the poorly named properties which we’re provided by the language, but the relationships do make sense. There are patterns. Understanding these patterns allows us to masterfully manipulate the whole family of objects that lives in our browser.

***ADDITION***

How OLOO changes the story

The story told above assumes object creation through a constructor function and the new keyword, the common way of mimicking classes in JavaScript. But there is a better way (read this chapter to see why)! To take advantage of JavaScript’s natural tendency towards behavior delegation, prefer Objects Linked to Other Objects, and greatly simplify your code. But there are some changes to note.

Recall our players from the story above, Creature and baby. Using OLOO, Creature will be the capitalized delegate and baby will be a ‘delegator’ but both will just be objects created like this:

var Creature = {}

var baby = Object.create(Creature)

All this does is create two objects, with baby delegating to Creature. There are no prototype objects to think about because there are no functions involved. Creature itself, is the prototype of baby, which makes more sense.

baby.__proto__ === Creature

Further up the prototype chain, things are the same, because the built-in Object and Function constructor functions and their respective prototype objects, do exist. So, for example,

Creature.__proto__ === Object.prototype

I started the story above with a stretch of the truth when I said that baby’s “constructor is how it was made, Creature”. This was actually just a convenient side-effect which provided us a natural mental model for how these objects are linked in the classical pattern. However, baby doesn’t really have a constructor property of its own. Only function prototype objects have constructor properties.

Object.prototype.hasOwnProperty(“constructor”) === true

Function.prototype.hasOwnProperty(“constructor”) === true

The constructor property call above was finding the value on the object that baby delegated to, Creature’s prototype object. In this case, baby delegates to Creature itself, which doesn’t have a constructor property either so it delegates further up to Object’s prototype object.

baby.constructor === Creature.constructor === Object.prototype.constructor === Object

Again, baby and Creature are clearly both just objects created by the built-in Object constructor.

It’s important to understand the intricate connections of the poorly named properties in the story above, but we don’t have to deal with them so much if we use this more natural OLOO design. All objects we create will be constructed from Object and all functions we create will be constructed from Function. The only thing we need to worry about is how to link our objects to each other in order to delegate behaviors appropriately.