An Easy Explanation to Prototypal Delegation in JavaScript
JavaScript language stands on two pillars: functional programming and prototypal delegation. The addition of classes in JavaScript is mere a syntactic sugar to give it Object-oriented programming feel: unwrap them and you will find functions inside.
Prototypal Delegation
Prototypal delegation is all about delegating the responsibility to the prototype higher up in the [[Prototype]] chain.
The prototype chain will look like this:
foo → Function.prototype → Object.prototype → null
In simple words, if you try to look for a property that is not owned by the object, the JavaScript engine will traverse up its prototype chain until it finds it. Let’s see an example to understand it.
The prototype chain will look like this:
recipe → recipeBook → Object.prototype → null
The object recipe doesn’t own the getRecipeName property. But by setting recipeBook as its prototype, we have delegated the job of printing the name to the recipeBook instance. This is called the prototypal delegation.
Now, let say you also want the recipe to delegate the task of orderRecipe() to another instance order. You can do this by extending the prototype chain like:
The prototype chain will extend to this:
recipe → recipeBook → order → Object.prototype → null
Now, I think it should be easy to relate why you are able to invoke recipe.hasOwnProperty() even though none of the object literals we declared owned hasOwnProperty. This is because all object literals implicitly inherit from Object.prototype, which means the hasOwnProptery() task has been delegated to Object.protoype.
Here’s the full code example:
Constructor function and the new keyword
Before I leave you with this delegation concept, I also want to talk about constructor functions and why do you need to use the new operator when creating instances. I hope with the prototype concept aside it should be easy to demystify their existence.
Every function in JavaScript has a property called prototype which is just a plain object with constructor property. This is different from the internal [[Prototype]] relationship.
Let’s revisit the previous recipe example and see how can you establish the same prototypal relationship using the constructor function.
Visually it will look similar to the diagram below:
The property (prototype) is special because when you invoke Recipe() using the new operator, the new operator uses Recipe.prototype as a prototype for instances it creates. Once the instance is created, the new operator passes that instance as this internally as one of the parameters to Recipe().
Now, it should be clear that why do we need to add properties to Recipe.prototype: they become available on all the Recipe instances via prototypal delegation.
__proto__ is a pseudo property for accessing the prototype of an object
Similarly, we can extend the chain and delegate the task of ordering the recipe to another object by setting it as a Recipe.prototype prototype.
The complete code example using Function constructor looks like:
Here’s how the final prototype chain looks like:
Closing thoughts
Prototypes in JavaScript may seem daunting to begin with, but I hope this article has eased your learning path. Understanding the foundation of JavaScript is the key to become a good developer. If you want to explore more about the prototype chain, then I highly recommend reading this chapter by Dr. Axel. Thank you for reading 😍.