Recently at a coding crash course I was doing for The Iron Yard, a former colleague of mine asked me if Objects in Javascript have 2 prototypes. At first, I wasn't sure what led him to think that. He is a Rubyist trying to learn JS and was confused when he would inspect objects and sometimes see a prototype property and sometimes a __proto__. Let's discuss the difference.

__proto__

The key to understanding the difference is in understanding the way that objects in Javascript delegate to one another, also known as prototypal inheritance.

First, let me say that I think the term prototypal inheritance is itself, a confusing term. This is because objects don't really inherit, they delegate. Most people when they hear the word "inheritance", they think of how children inherit traits from their parents. This makes sense in the way that classical inheritance works.

Let's consider a parent Sam. Sam has brown hair and gives birth to a baby named Noah. Noah also has brown hair, he inherited that trait from his mother. If Sam dies her hair blonde, it will have no affect on the color of Noah's hair. This is how classical inheritance works. This metaphor breaks down even for classical inheritance once Sam has another baby because her second born would still have brown hair as well. However, when looking at this family through the lens of prototypal inheritance, not only would Sam's second born have blonde hair, Noah would too.

How could Noah's hair appear blonde solely because his mother died her hair after he was born? Because the way prototypal inheritance works; when you are looking at Noah's hair, you are actually looking at Sam's hair. Noah doesn't even have his own hair, he delegates that to his mother.

let's describe this relationship with some code. You can make a new object that delegates to an existing object, using Object.create. However, I think it makes the idea more understandable if we simply wrap this in a function called delegateTo:

function delegateTo(delegatee) {  
  return Object.create(delegatee);
}

Now let's create Sam and Noah:

var sam = {  
  hairColor: "brown";
}

var noah = delegateTo(sam);

sam.hairColor; // brown  
noah.hairColor; // brown

sam.hairColor = "blonde";

noah.hairColor; // blonde

sam.hasOwnProperty("hairColor"); // true  
noah.hasOwnProperty("hairColor"); // false  

If you do some introspection of Noah, you will find that he has a __proto__ property that points to Sam.

When you access a property on Noah, if Noah has that property himself (hasOwnProperty), then it will be used. If not, the next thing that will be checked is Noah's __proto__, which happens to be Sam. If Sam has the property, it will use hers, if not it will check her __proto__. Yes, Sam has a __proto__ as well, and it points to Object.

So in essence, the __proto__ is the object that the current object delegates to.

let's look at another example.

var soldier = {};  
soldier.fight = function() {  
  console.log('the soldier engages the enemy.');
}

var sergeant = delegateTo(soldier);  
sergeant.recon = function() {  
  console.log('the sergeant recons the area.');
}

var captain = delegateTo(sergeant);  
captain.lead = function() {  
  console.log('the captain leads the troops.');
}

var colonel = delegateTo(captain);  
colonel.plan = function() {  
  console.log('the colonel strategizes the attack.');
}

Now consider what happens when you execute colonel.recon()

  1. The first thing that happens is that colonel is checked for the property recon on itself. It's not found so it continues down the delegation chain.

  2. The next thing that is checked for the recon property is the captain which does not have it either so it's __proto__ (sergeant) gets checked next.

  3. The sergeant delegates to the soldier, but since the sergeant has the recon property itself, it gets invoked and the soldier is never checked.

prototype

Before we jump strait into what the prototype is, let's first consider that soldier object we created.

Anyone with the slightest understanding of the art of war should understand that a single soldier by themselves is not likely going to win any battles. You need an army. let's write a function that can generate new soldiers.

var SoldierPrototype = {  
  fight: function() {
    console.log('the soldier engages the enemy.');
  }
}

function generateSoldier() {  
  var soldier = delegateTo(SoldierPrototype);
  return soldier;
}

var pfc = generateSoldier();  
var cpl = generateSoldier();  
var spc = generateSoldier();  

Now each of the three soldiers pfc, cpl, and spc are delegating to the SoldierPrototype. So when the fight method is invoked on any of them, they delegate to the fight function on the prototype. This also means that if the fight method on the prototype were changed, it will affect all the existing soldiers.

Functions have a special property in Javascript. this is called the prototype property. Using this property you could rewrite the previous code like so:

var SoldierPrototype = {  
  fight: function() {
    console.log('the soldier engages the enemy.');
  }
}

function Soldier() {}

Soldier.prototype = SoldierPrototype;

var pfc = new Soldier();  
var cpl = new Soldier();  
var spc = new Soldier();  

Or like:

function Soldier() {}

Soldier.prototype = {  
  fight: function() {
    console.log('the soldier engages the enemy.');
  }
};

var pfc = new Soldier();  
var cpl = new Soldier();  
var spc = new Soldier();  

When you set the prototype property on a function, and invoke it with the new operator. It behaves very similarly to our delegateTo function (or Object.create.) It creates a new object that delegates to that prototype object. Using a function this way is also referred to as a constructor.

The unique thing about constructor functions is that inside the context of the function the this keyword refers to the new object being created and gives an opportunity to assign properties directly on that new object.

let's look at a common gotcha.

function Soldier() {}  
Soldier.prototype = {  
  weapons: ['rifle', 'grenade', 'bayonet'],
  weaponOfChoice: 'rifle'
};

var GIJoe = new Soldier();  
var Rambo = new Soldier();

Rambo.weaponOfChoice = 'compound bow';  
Rambo.weapons.push(Rambo.weaponOfChoice);

console.log(GIJoe.weaponOfChoice);  
// > rifle

console.log(GIJoe.weapons);  
// > ['rifle', 'grenade', 'bayonet', 'compound bow']

So what happened here? Changing one property affected the prototype and changing another did not. let's tackle these one at a time.

The first one:

Rambo.weaponOfChoice = 'compound bow';  

This expression is an assignment, so the prototype chain is never checked. The property is just added to the Rambo object. In fact, if you were to inspect Rambo, you would see that Rambo and it's __proto__ object both have the weaponOfChoice property. So now when accessing this property, the __proto__ object is no longer checked.

Now let's look at the other:

Rambo.weapons.push(Rambo.weaponOfChoice);  

This is not an assignment. The weapons property on Rambo is being looked up and found on Rambo's __proto__. Then a value is being added to it. This causes it to affect all other objects that are delegating to the same __proto__.

This can be avoided by assigning the weapons array as a property directly on the new object inside the constructor:

function Soldier() {  
  this.weapons = ['rifle', 'grenade', 'bayonet'];
}
Soldier.prototype = {  
  weaponOfChoice: 'rifle'
};


Conclusion

The prototype is a property on a constructor function that sets what will become the __proto__ property on the constructed object. The __proto__ is a special property on all objects specifying what object to delegate to if the accessed property is not found on the current object. The __proto__ can chain several objects together (also known as the prototype chain) and always ends at Object.

Let me know in the comments if you found this article useful.

Please note when I say children/parent in this context, I am not referring to a hierarchical structure, I am writing about human beings.

© 2017. All Rights Reserved.

Proudly published with Ghost