Prototypes in JS

JavaScript's Prototype's

If you've never really taken the time to fully immerse yourself in Javascript, prototypes can be kind of confusing. What's the deal with Array.prototype.sort()? Where was this "prototype" attribute defined? How can I use it to my advantage? Well, trust me, it really is a lot easier than it looks. This post will attempt to demystify what some people might consider one of the more conceptually difficult aspects of Javascript. To put it very briefly, the prototype property allows for inheritance in Javascript. That's basically it. The rest is semantics. Article over.

Just kidding. Sorta.

First things first, let's start with a definition: a prototype is just a preliminary model of something. In other words, a prototype is a set of inherited traits belonging to another object. So prototypes appear to be some mechanism of inheritance, but how do we use it? This is probably better explained with an example. Let's use rabbits. What properties does a rabbit have that make it a rabbit? Ears? Sure. Fur? Why not. Likes carrots? I guess. So how might we model this rabbit in a more traditional object-oriented language like Java? Well, you'd create a class and add some attributes to it and any instantiation of that class would automatically include these attributes and we'd have our rabbit. Awesome. But wait a minute...Javascript doesn't really have classes (ignoring ES6+ for a minute). What now? How can we be more object oriented and allow for inheritance? Enter the prototype property.

Protyping is Javascript's version of inheritance. Sound good? Let's see a straight-forward example:

// First let's create an object (\_everything\_ in JS is an object, remember)

function Rabbit() {

  // nothin' here yet

}



// Let's instantiate a rabbit

var bugs = new Rabbit();

console.log(bugs.ears); // false... better add some ears then



Rabbit.prototype.ears = true;



// Let's try again...

console.log(bugs.ears); // true... nice



// Let's create another rabbit

var anotherRabbit = new Rabbit();



console.log(anotherRabbit.ears); // true

As you can see from above, we created a Rabbit object with zero attributes. We then instantiated this object as bugs wherein we checked to see if bugs had any ears, which he didn't. So, we put some ears onto the original object via the prototype property after which bugs was found to possess. Furthermore, we instantiated anotherRabbit which also inherited its ears from the Rabbit object.

If that's all you take away from this article, you're still doing pretty good. There are a few other subtleties to prototypes, but what's really important is to understand that it's just Javascript's way of achieving object inheritance.

Prototype Chain

The way in which Javascript's runtime checks for various properties is to first check the object that was directly called and then to check the prototype attribute of that object and so-on and so-forth until a final prototype object is checked. If that property/attribute is not found at that object you'll either get an undefined or a TypeError depending on what you tried to call.

Before moving forward it's worth noting that the term 'prototype attribute' here is really just an annoying way of saying the object's parent, this may also be referred to as the 'prototype object'. But really, when you see those two terms just think, "They mean parent object". So this term 'prototype chain' just refers to the lineage of an object. How about an example of a prototype chain? Don't mind if I do.

// Setup the grandparent object...

function Mammal(){

  this.hasFur = true;

  this.hasLiveYoung = true;

}



// Setup parent object...

function Lagomorph(){

  this.isHerbivore = true;

  this.hasFourIncisors = true;

}



// Setup child object...

function Rabbit(){

  this.eatsCarrots = true;

}



// Setup the lineage...

Lagomorph.prototype = new Mammal();

Rabbit.prototype = new Lagomorph();

var bugs = new Rabbit();

Let's see what happens when I try to call hasLiveYoung on an instantiated Rabbit

bugs.hasLiveYoung; // true

I hope it's obvious what just happened. Our Rabbit object just displayed an attribute that was clearly defined only in the Mammal object. Pretty cool.The benefit of all this, and the benefit with object behavior in Javascript overall, is how dynamic object creation and inheritance is. The prototype properties of objects allow us to be more efficient with code reuse, inheritance, and keeping the object-oriented gods happy.