Prototype in Javascript - 02 - The __proto__ property
Tags: javascript, oop, prototype
Published: 2020-03-22 13:48:57

In our previous article, we looked at a few ways of creating objects. However, we did run into an interesting problem, namely that of unnecessary code reuse. Let us try to understand it better with an example.

```javascript
    let bird1 = {
      type: 'sparrow',
      canFly: true
    }

    let bird2 = {
      type: 'eagle',
      canFly: true
    }
```

We have created 2 objects, `bird1` and `bird2`. We can see that while the value of the *type* property differs, the value of the canFly property remains the same. Rather than have the same property repeated in both objects, wouldn't it be better if we could have a single object called `bird`, which has a property canFly set to true (if we assume that all birds can fly), and somehow let Javascript know that both the `bird1` and `bird2 ` object are going to be inheriting (or copying) the properties of that `bird` object? In this way, we could have a single `bird` object in which we could store all the properties that are common in birds and only need to include the unique properties in `bird1` and `bird2`. Something like this

```javascript
    let bird = {
      canFly: true,
      laysEggs: true,
      hasFourLegs: false 
    }

    let sparrow = {
      color: 'blue'
    }

    let eagle = {
      color: 'brown'
    }

console.log(sparrow.canFly); // Returns undefined now but we ideally want a scenario where it returns true
```

Javascript allows us to implement the above concept with the special property of an object called **[[Prototype]]**.

## [[Prototype]]

In Javascript, objects have an internal property [[Prototype]], which is either another object or null. Although [[Protoype]] is the name given in the ECMAScript specification, for the purposes of this article, we shall be using the term 'prototype'.

The prototype of a Javascript object can be considered as its parent object or its super object. This means that when we try to access a property in an object, and it's missing, Javascript then tries to look for that property in the object's prototype and access it. This is referred to as 'prototypal inheritance'. 

Although the prototype is an internal and hidden property of an object, there are other ways to access it. One of them is to use the '\_\_proto\_\_' keyword. 

## The \_\_proto\_\_ property

Let us see an example of using the *\_\_proto\_\_* property for our previous example.

```javascript
    let bird = {
      canFly: true;
      laysEggs: true;
      hasFourLegs: false 
    }

    let sparrow = {
      color: 'blue'
    }

    let eagle = {
      color: 'brown'
    }

    sparrow.__proto__ = bird;
    eage.__proto__ = bird;

    console.log(sparrow.canFly); // Returns true
```

In the above code, you can see that we have set the prototype of `sparrow` as `bird` using the *\_\_proto\_\_* property. Now, when we try to access the *canFly* property of `sparrow`, Javascript first looks for it in `sparrow`. When it doesn't find it there, Javascript then searches for it in its prototype (in this case, `bird`) and finds it there. Hence, sparrow.canFly is evaluated to true. Similarly, since the prototype of `eagle` is set to `bird` too, eagle.canFly also works and evaluates to true.

In the above example, we can say that `bird` is the prototype of `sparrow`, or that that `sparrow` 'prototypically inherits' inherits from 'bird'. The properties of `bird`, namely *canFly*, *laysEggs* and *has4Legs*, are called as inherited properties.

We can chain prototypes too.

```javascript
    let object1 = {
      property1: 'exists'
    }

    let object2 = {
      property2: 'exists'
      __proto__: object1
    }

    let object3 = {
      property3: 'exists'
      __proto__: object2
    }

    console.log(object3.property1); // 'exists'
```

When we look for *property1* in `object3`, Javascript doesn't find it. It then looks for it in its prototype, which is `object2`. It doesn't find *property1* in `object2`, and further looks for it in `object2`'s prototype (which is `object1`). It then finds *property1* in `object1` and returns its value.

Now, you might be wondering, in the above example, what is the value of the prototype of `object1`? Is it going to be `undefined`, or is it an empty object? The answer is that it will be `null` since the prototype is an internal property of every object in Javascript, which can either be another object or null.

In fact, there's a more elegant way of specifying an object's prototype while creating it itself. It's done via the `Object.create` function.

## Object.create

Calling the `Object.create` function does 3 things:

1. Create an empty object
2. Set the prototype of the newly created object as the argument passed in the Object.create() function. This argument is mandatory and can only be either another object or null.
3. Return the created object.

```javascript
    let object1 = {
      property1: 'exists'
    }

    let object2 = Object.create(object1);

    console.log(object2.property1); // 'exists'
```

Hence, as we have seen so far, we can make use of the hidden [[Prototype]] property in Javascript to implement the concept of inheritance and organize our code in a much more efficient and structured manner. In the next article of this series, we shall be discussing the `new` keyword and how it functions under the hood to create objects in Javascript.