Prototypal Inheritance 3: Embrace prototypal linking also called OLOO

What's the best way to use the power of Prototype?
Let's see how we can create flexible and easy to separate code with strong architecture.

[ The content of this article is my take home from the great book of Kyle Simpson this & Object Prototypes of the series "You don't know JS", i really recommend to read it in order to fully grab these concepts! ]


Here you can find the previous posts of this series:
Prototypal Inheritance 1
Prototypal Inheritance 2


In the previous posts we analize why is not wise to use classical-inheritance way of thinking with Javascript and the reasons why even if we perfectly emulate classical-inheritance into javascript code, the language will still work in different way, leading to unespected behaviours.

OLOO

Now the question is: How can we properly work with this [[Prototype]]?
We keep saying is powerful and even better then classical-inheritance but how actually we can use this power to our advatage?
Well, Kyle Simpson guide us trhough what he call Object Linked to Other Object or simpler OLOO.
To understand what is this about we need to think in behaviour-delegation design pattern way, so if you come from class-based languages and spent most of your life programming with classical-inheritance design pattern, this could be more challenging (but we are all sure you will make it!)

From now on instead of saying prototypal-inheritance (which, we already explain in the previous post is confiusing term) we say behaviour-delegation.

How to think in this way?

  • First, we need to create an Object which will have concrete behaviour on it which are utility methods that other objects can use.

  • Then, we will create others Objects which hold specific data/behaviour

  • As last, we link the behaviour-specific Object to the "main" utility Object, allowing to delegate to it.

Basically there are some behaviours (the ones into utility Object) that are needed from other Objects (behaviour-specific objects) and they can be accessed by those Objects whenever it's needed, using delegation.
This is done without being forced to copy all those utility-behaviours and carry them around even if we might not need all of them; we keep them in separate objects and access them just when we actually need them.

Practice

Let's put in practice what we just said:

Let's say we have many similar Tasks that we need to model.

1_ We define utility-behaviour Object called Task

Task = {  
  setID: function(ID) {this.id = ID;},
  outputID: function() {console.log(this.id);}
}

2_ We define an Object which is linked to the utility Object Task

ABC = Object.create(Task);  

3_ Now we define the specific behaviour/data for the tasks Object

ABC.prepareTask = function(ID, Label){  
  this.setID(ID);
  this.label = Label;
}

Now is very easy to keep going and create others subtasks objects:

DEF = Object.create(Task);  
DEF.setUpTask = function() { ... }  

Make sense, doesn't it? Is clean and easy to read.
Here some difference between class and delegation:

  1. On delegation you want the state to be on the delgators (ABC, DEF) not on the delegate Object (Task)

  2. In delegation we try to avoid shadowing as much as possible so we avoid possible messy and brittle code.
    Doing so we make also our code more redable because we are force to use different method's names making them more specific.

  3. General utitlity's methods on Task are available to us because ABC can delegate to it: Object delegation is really powerful. We have to start thinking of objects as peers. Not in vertical but side by side.

Important to notice is that you cannot link more then two Objects together nor can you create a circle delegation.
If A is link to B and then you try to link B to A, you get error.

Here following two example of Javascript code first written using classical(prototypal) inheritance code style and later using OLOO style.

Prototypal OO Style

function Foo(){  
  this.me = who;
}

Foo.prototype.identify = function(){  
  return "I am" + this.me;
} 

function Bar (who){  
  Foo.call(this, who);
}

Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.speak = function(){  
  alert('hello,' + this.identify() + '.')
}

var b1 = new Bar('b1');  
var b2 = new Bar('b2')  
b1.speak();  
b2.speak();  

OLOO Style

Foo = {  
  init: function(who){
    this.me = who;
  },
  identify: function() {
    return "I am" + this.me;
  }
}

Bar = Object.create(Foo);  
Bar.speak = function() {  
  alert('Hello' + this.identify() + '.');
} 

var b1 = Object.create(Bar);  
b1.init('b1');  
var b2 = Object.create(Bar);  
b2.init('b2');  
b1.speak(); // Hello b1.  
b2.speak(); // Hellow b2.  

Conclusion

As last step of "prototypal inheritance" we learnt a great way to fully use the power of prototype.
OLOO better supports the principle of separation of concerns and avoid confusion on how javascript behave.

To recap our whole journey on learning prototype link in Javascript:

  • In Javascript there are no Class since is not based on class but on prototype. Therefore is not possible to write classical inheritance.

  • Often classical inheritance design style is emulate in javascript doing what is called prototypal inheritance. This term and also this code style lead to confusion and lead developers to think that javascript can actually act as class-base language and copy behaviour into child Objctes.
    This is not true, since even if we emulate classical-inheritance design style, javascript will still create link between two objects instead of copy Class behvaiour into the Child.

  • Prototypal inheritance is preferable to classical one because is loose coupoling, has flat hierarchies, make multiple inheritance easy and doesn't lead to brittle architecture.
    With Class you have to inherite everything from the Class even if you don't need all of it which lead to have huge subclass. Using delegation we take the methods we need, when we need them.