Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 18, 2020 11:14 am GMT

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.

function foo(){}Object.getPrototypeOf(foo) === Function.prototype; // trueObject.getPrototypeOf(Function.prototype) === Object.prototype; // trueObject.getPrototypeOf(Object.prototype); // null
Enter fullscreen mode Exit fullscreen mode

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.

const recipe = { name: "Garlic Naan" };const recipeBook = {  getRecipeName() {    console.log(this.name);  },};// Set 'recipeBook' as the prototype of 'recipe'Object.setPrototypeOf(recipe, recipeBook);// Prototypal delegation in actionrecipe.getRecipeName(); // prints 'Garlic Naan'
Enter fullscreen mode Exit fullscreen mode

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 recipe to delegate the task of orderRecipe() to another instance order. You can do this by extending the prototype chain like:

const order = {  orderRecipe() {    console.log(`${this.name} ordered!`);  },};// Extending the prototype chainObject.setPrototypeOf(recipeBook, order);recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
Enter fullscreen mode Exit fullscreen mode

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 complete code example:

const recipe = { name: "Garlic Naan" };const recipeBook = {  getRecipeName() {    console.log(this.name);  },};// Set 'recipeBook' as the prototype of 'recipe'Object.setPrototypeOf(recipe, recipeBook);const order = {  orderRecipe() {    console.log(`${this.name} ordered!`);  },};// Extending the prototype chainObject.setPrototypeOf(recipeBook, order);// Prototypal delegation in actionrecipe.getRecipeName(); // prints 'Garlic Naan'recipe.orderRecipe(); // prints 'Garlic Naan ordered!'recipe.hasOwnProperty("name"); //true
Enter fullscreen mode Exit fullscreen mode

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.

// Constructor function 'Recipe'function Recipe(name) {  this.name;}Recipe.hasOwnProperty("prototype"); // trueRecipe.prototype.constructor === Recipe; // true
Enter fullscreen mode Exit fullscreen mode

Visually it will look similar to the diagram below:

Constructor function

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().

const recipe = new Recipe('Garlic Naan');
Enter fullscreen mode Exit fullscreen mode

Recipe instance delegates the task to its prototype

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

// Adding properties to 'Recipe.prototype' will make them // available on all `Recipe` instances. Recipe.prototype.getRecipeName = function () {  console.log(this.name);}; 
Enter fullscreen mode Exit fullscreen mode

Adding properties to prototype
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.

// Order constructorfunction Order() {}Order.prototype.recipeOrder = {  recipeOrder() {    console.log(`${this.name} ordered!`);  },};// Setting up the delegation aka Prototypal inheritanceObject.setPrototypeOf(Recipe.prototype, Order.prototype);recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
Enter fullscreen mode Exit fullscreen mode

The complete code example using Function constructor looks like:

// Constructor function 'Recipe'function Recipe(name){this.name}Recipe.hasOwnProperty('prototype'); // trueRecipe.prototype.constructor === Recipe; // trueconst recipe = new Recipe('Garlic Naan');Recipe.prototype.getName = function () {  console.log(this.name);};// Order constructorfunction Order() {}Order.prototype.recipeOrder = {  recipeOrder() {    console.log(`${this.name} ordered!`);  },};// Setting up the delegation aka Prototypal inheritanceObject.setPrototypeOf(Recipe.prototype, Order.prototype);// Prototypal delegation in actionrecipe.getRecipeName(); // prints 'Garlic Naan'recipe.orderRecipe(); // prints 'Garlic Naan ordered!'recipe.hasOwnProperty("name"); //true
Enter fullscreen mode Exit fullscreen mode

Here's how the final prototype chain looks like:
Alt Text

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 .


Original Link: https://dev.to/aman_singh/an-easy-explanation-to-prototypal-delegation-in-javascript-3ok2

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To