Prototypal inheritance of Instantiated vs Non-Instantiated Objects in Javascript

I recently read The Principles of Object-Oriented JavaScript by Nicholas Zakas and was enthralled by his patterns for prototypal inheritance of both instantiated and non-instantiated objects.   As I put each of these patterns to practice I noticed an interesting “discrepancy” between the the way each was linked to its parent.  I thought it was interesting enough for me to dig into, so it might make an interesting blog post.

Example 1: Instantiated Object Inheritance

In the example below, we create our parent class “Animal” which is created via the function method.  We attach a simple method to the prototype which retrieves the private “species” variable.

Then we create a “Dog” subclass by creating it via the function method, then linking the two classes with

Dog.prototype = Object.create(Animal.prototype);

This overrides the default Dog prototype with the Animal prototype, resulting in the correct prototype chain.  Here is a very abbreviated version of the prototype chain.

Screen Shot 2014-05-14 at 4.43.33 PM

Note the very important constructor attachment required after we override the prototype.

Dog.prototype.constructor = Dog;

Pretty common sequence to chain these two classes together.  Any changes made to Animal will get automatically chained to Dog.  Now let’s take a look at the non-instantiated example.

Example 2: Non-instantiated Object Inheritance

In this example we’ll use a IIFE (Immediately-invoked functional expression) to create our parent class, with our retrieval function as above.  This pattern is common for singleton type use cases.

Now notice how we chain the prototypes of the Animal and Dog classes, specifically what is passed to the Object.create() function.

var myDog = Object.create(animal);

No mention of a prototype!  Why not?  Why are we attaching the object itself instead of its prototype?

The reason is because of what Animal is in this second example.  In example 1, Animal was created via the function literal resulting in an object with a full prototype chain inherited from Function. In the second example, animal was created via the inline object declaration “{}” resulting in an object with a prototype of “null”. To put it shortly, an object only has a prototype property if it was created via function literal.

Screen Shot 2014-05-14 at 4.43.40 PM

So if you called the following code, you would get a big fat error because animal has no prototype property.

var myDog = Object.create(animal.prototype); //TypeError

So in example 2, the Animal object itself is what gets chained to myDog. MyDog  can now add its own methods without modifying the original Animal object.

 

Leave a Reply

Your email address will not be published. Required fields are marked *