An Easy Explanation to Prototypal Delegation in JavaScript
Tags: javascript, webdev, prototypes, functional
Published: 2020-10-18 11:14:27

JavaScript language stands on two pillars: [functional programming](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0) 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. 

```js
function foo(){}

Object.getPrototypeOf(foo) === Function.prototype; // true
Object.getPrototypeOf(Function.prototype) === Object.prototype; // true
Object.getPrototypeOf(Object.prototype); // null
```
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.

```js
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 action
recipe.getRecipeName(); // prints 'Garlic Naan'
```
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:

```js
const order = {
  orderRecipe() {
    console.log(`${this.name} ordered!`);
  },
};

// Extending the prototype chain
Object.setPrototypeOf(recipeBook, order);

recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
```
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**](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes), which means the `hasOwnProptery()` task has been delegated to `Object.protoype`. 

Here's the complete code example: 
```js
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 chain
Object.setPrototypeOf(recipeBook, order);

// Prototypal delegation in action
recipe.getRecipeName(); // prints 'Garlic Naan'
recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
recipe.hasOwnProperty("name"); //true
```

## Constructor function and the new keyword

Before I leave you with this delegation concept, I also want to talk about [constructor functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function) and why do you need to use the [**new**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new) operator when creating instances. I hope with the prototype concept aside it should be easy to demystify their existence. 

Every function ([except fat arrow](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#use_of_prototype_property)) 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.

```js
// Constructor function 'Recipe'
function Recipe(name) {
  this.name;
}

Recipe.hasOwnProperty("prototype"); // true
Recipe.prototype.constructor === Recipe; // true
```
Visually it will look similar to the diagram below: 

![Constructor function](https://dev-to-uploads.s3.amazonaws.com/i/k4jflqxwdgkcbw0b9aei.png)

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

```js
const recipe = new Recipe('Garlic Naan');
```
![Recipe instance delegates the task to its prototype](https://dev-to-uploads.s3.amazonaws.com/i/opgg6phne0ke7d04rd4s.png)

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

```js
// Adding properties to 'Recipe.prototype' will make them 
// available on all `Recipe` instances. 
Recipe.prototype.getRecipeName = function () {
  console.log(this.name);
}; 
```
![Adding properties to prototype](https://dev-to-uploads.s3.amazonaws.com/i/kj6cp4gdvwwjqo3tzdy1.png)
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.

```js
// Order constructor
function Order() {}

Order.prototype.recipeOrder = {
  recipeOrder() {
    console.log(`${this.name} ordered!`);
  },
};

// Setting up the delegation aka Prototypal inheritance
Object.setPrototypeOf(Recipe.prototype, Order.prototype);

recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
```
The complete code example using Function constructor looks like:
```js
// Constructor function 'Recipe'
function Recipe(name){this.name}

Recipe.hasOwnProperty('prototype'); // true
Recipe.prototype.constructor === Recipe; // true

const recipe = new Recipe('Garlic Naan');

Recipe.prototype.getName = function () {
  console.log(this.name);
};

// Order constructor
function Order() {}

Order.prototype.recipeOrder = {
  recipeOrder() {
    console.log(`${this.name} ordered!`);
  },
};

// Setting up the delegation aka Prototypal inheritance
Object.setPrototypeOf(Recipe.prototype, Order.prototype);

// Prototypal delegation in action
recipe.getRecipeName(); // prints 'Garlic Naan'
recipe.orderRecipe(); // prints 'Garlic Naan ordered!'
recipe.hasOwnProperty("name"); //true

```
Here's how the final prototype chain looks like: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a5nxevviutg3lvz5jpjb.png)

---

## 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](https://exploringjs.com/impatient-js/ch_proto-chains-classes.html#prototype-chains) by Dr. Axel. Thank you for reading 😍.