JavaScript Prototypes: Your one stop guide for understanding this core JavaScript concept.

Photo by Growtika on Unsplash

JavaScript Prototypes: Your one stop guide for understanding this core JavaScript concept.

Prototypes are the core of how JavaScript functions. Whether you are preparing for you next interview, or you just want to dive deep into the world of JavaScript, this guide should give you a solid grasp on prototypes in JavaScript. Let us begin.

But firstly, what is a prototype?

Simply put, a prototype is a mechanism using which objects in JavaScript inherit features from one another. This prototype inherits its own features from another prototype, which is what we call prototype chaining, but we shall discuss that later in this tutorial.

//take a simple object
const a = {                            // Prototype Chain
    name: "Anubhav",                   // Object -> null
    age: 23
}
a.__proto__

In order to get to the parent class of an object, we use the “__proto__” notation. On running the above piece of code in the browser console, we get the following result.

Now it may look like a lot is happening, but I want you to focus on the “__proto__“ bit. Essentially what is happening is that we are fetching the parent class of this object that we created, and the parent “__proto__“ is null. This means that the prototype chain for this very example ends here. The proto of any object you create does not always point to the Object.prototype. The next example will make things a lot clearer.

// consider a number here
const a = 10                        // Prototype Chain
a.__proto__                        // const a -> number -> Object -> null

Upon running this on console, we get the following. Focus only on the “__proto__“ part.

In case of “const a”, which is an integer, we see that its protoype points to the Number class in javascript, which makes sense too. But look what happens when I try to check the proto of the Number class.

It is just another javascript object, just like we saw in our previous example. Additionally, any further proto for this object points to null as shown below.

Similar is the case for strings where it first points to the String class, then to the Object and finally to null. This is what we refer to as a prototype chain.

Note: The __proto__ is compatible with most browsers but one should not use it in production level code as it may be replaced by Object.getPrototypeOf() in the future.

How to set up a prototype?

There are multiple ways of setting up an object’s prototype, of which, we shall be discussing a couple here.

  1. Using Object.create

    In this method, we create a new object that allows us to specify an object that will be used as the prototype of the new object.

     const PrototypeOfCar = {
         model(){
         console.log("Virtus")
     }
     }
     const vw = Object.create(PrototypeOfCar)
     vw.model();
    

    In the above code block, we made an object called PrototypeOfCar which has the model() method. Now we use the Object.create() to create a new object with PrototypeOfCar as its prototype. Then, we can call the model method on this newly created object and the prototype provides its implementation.

  2. Using a constructor

    When a function is called as a constructor, the prototype property is set as the prototype of the newly constructed object. This means that if we set the prototype of a constructor, we can ensure that all the objects created using that constructor are given that aforementioned prototype.

     const prototypeOfCar = {
         model(){
         console.log(`hello, my name is ${this.name}!`);
     }
     }
     function Car(name){
         this.name = name;
     }
     Car.prototype.model = prototypeOfCar.model
    

    In the above code, we create an object prototypeOfCar which has a model() method. We then create a Car() constructor function which initializes the name of the car to create. Now what this does is whenever we try to create any object using the Car() constructor, it will get Car.prototype as its prototype, which by itself contains the model() method.

Shadowing

Suppose you try to access a method on an object that is not defined. What do you think is going to happen? Well, it tries to go up in the prototype chain to find it. Let us see an example.

function Person(name) {
    this.name = name
    age= 23
}
const p1 = new Person("Daniel")
Person.prototype.greet = () =>{
    return "Good afternoon"
}
// p1.greet = function(){
//     console.log("Good Morning")
// }
console.log(p1.greet())

In the above code, the p1 does not have the greet method initially, hence it goes up its prototype chain to find it and that is the reason “Good Afternoon “is printed to the console.

Now, upon adding a greet method directly to the p1 object with the same name, it directly calls the greet() method without having to move up its prototype chain to find it, and that’s the reason “Good Morning “is printed in the console. This is shadowing in action.

Conclusion

In this blog, we looked at how prototypes work under the hood, how prototype chains look like, methods to set up your custom prototype and we also learned about how shadowing works. In essence, prototype provide a way for one object to use the methods and properties of its prototype objects via linkages. I hope this blog was helpful for anyone reading it. Thank you.

Did you find this article valuable?

Support Anubhav's Blog by becoming a sponsor. Any amount is appreciated!