Prototypes in JavaScript | JavaScript & Object Oriented Programming | Part 11

In the Previous Tutorial, we explored Getters and Setters in JavaScript. In this tutorial, we’ll learn about Prototypes in JavaScript.

Inheritance is one of the most important aspects of Object-oriented programming. Unfortunately, JavaScript does not implement inheritance the same way as other modern programming languages like Java, C#, Python, etc do. In JavaScript, inheritance is implemented through Prototyping. There is huge hue and cry about Prototyping in JavaScript community for being so confusing and intimidating. This is partly because lots of online tutorials speaks of Prototyping as if they are CocaCola’s secret formula.

In this tutorial we’ll keep things simple and learn Prototypes by building a small application – a car factory.

Let us run this code in the browser console and build two cars.

function Car(make, model) {
    this.make = make;
    this.model = model;

    this.run = function() {
        console.log('Car is running');
    }
}

const c1 = new Car('Volkswagen', 'Polo');
const c2 = new Car('Toyota', 'Corolla');

Let us inspect both object c1 and c2 in the console:

It is looking as expected, right? Both objects have make, model and run properties. In fact, run is a method.

Hell No!!! What is that __proto__ thing?

Let us keep aside that weird __proto__ property for a moment. We’ll explain it in a few minutes.

The real issue is both objects have their own property run. They also have their own make and model properties but they are unique for both cars. Do we really need the duplicate properties run for both objects? Isn’t it would be efficient to keep that property run somewhere else that both objects can share.

That somewhere else is the prototype of that object. We can add the run property to the prototype of the constructor function Car (remember in JavaScript a function is also an object) and remove it from the function:

function Car(make, model) {
    this.make = make;
    this.model = model;
}

Car.prototype.run = function() {
    console.log('Car is running');
}
const c1 = new Car('Volkswagen', 'Polo');
const c2 = new Car('Toyota', 'Corolla');

If we refresh the browser and run this code in the browser console, both objects c1 and c2 will have two direct properties make and model and they will share the run property. In fact all objects created by Car will share the same run propertybecause this property is added to the constructor function’s prototype.

If you run c1.run() and c2.run(), you should be greeted with this message in both cases:

Car is running

Let us inspect c1 and c2 again in the browser console.

Where is the run property man? How come c1.run() is still working?

If we expand the __proto__ property for both objects c1 and c2, there we’ll find it.

run property inside __proto__ property

The __proto__ property of an object refers to its prototype, that is the prototype property of the function used to create that object.

In our case, the __proto__ property of objects c1 or c2 refers to the propertyprototype of function Car If we execute these statements we should be greeted with true:

c1.__proto__ == Car.prototype;  //true
c2.__proto__ == Car.prototype;  //true

Note: Just to be sure there are two underscores __ surrounding proto.

If we try to look up a property in an object, the JavaScript interpreter first tries to find it in that object’s own property, then looks for it in the object’s prototype. In our case, the JavaScript interpreter first tried to find run in c1‘s own properties, it did not find it there so it tried to find it in its prototype Car.prototype and it was successful.

We can confirm if a property is defined as the object’s own property by running this command:

c1.hasOwnProperty('make'); //true
c1.hasOwnProperty('run');  //false

Wait! How come c1 has got hasOwnProperty property? We did not define it in Car.

Well, that is an intelligent question. It is due to the prototypical chain. Let me explain it.

If you have followed This Tutorial, you know that the constructor functions are created by a special constructor function Function and this special constructor function Function is created by another special constructor function Object. That is why we call in JavaScript, everything is an object (except primitives).

Since every object in JavaScript is derived by Object, in the Prototypical Chain, Object.prototype is the last prototype to look for.

When we refer c1.hasOwnProperty, the JavaScript interpreter tries to find it in c1‘s own property. It fails to find it there so it tries to find it in its prototype Car.prototype (remember c1.__proto__ is just a reference to Car.prototype). The hasOwnProperty is still not found in Car‘s prototype. The JavaScript interpreter tries to find it upwards in the Prototypical Chain i.e Car.prototype.__proto__, which is just a reference of Object.prototype, and it finds it there.

Guys, we hope this tutorial was able to help you understand Prototypes in JavaScript. In the Next Tutorial, we’ll extend these learning and implement Inheritance by using Prototypes.

5 thoughts on “Prototypes in JavaScript | JavaScript & Object Oriented Programming | Part 11”

Leave a Reply