Javascript Tutorial
Javascript Tutorial Introduction to Javascript JavaScript Code Editors & IDE JavaScript Hello World Example Javascript Syntax and Rules syntax_rules javascript_identifiers JavaScript Keywords & Reserved Words javascript_variables JavaScript Const JavaScript let vs var vs const Data Types in JavaScript JavaScript String Template Literals & String interpolation in JavaScript Tagged Templates in JavaScript String to Number in JavaScript Number Data Type in JavaScript NaN in JavaScript JavaScript Number Min & Max & Safe Values JavaScript EPSILON & Floating point precision Infinity in JavaScript JavaScript Bigint BigInt Vs Number in JavaScript Boolean Data Type in JavaScript Undefined in JavaScript Null in JavaScript Null vs Undefined in JavaScript JavaScript Operators Arithmetic Operators in JavaScript Unary plus & minus operators in JavaScript Increment & Decrement Operators in JavaScript Comparison or Relational operators in JavaScript Strict Equality (==) Loose Equality (===) in JavaScript Ternary Conditional Operator in JavaScript Logical Operators in JavaScript Bitwise Operators in JavaScript Assignment Operators in JavaScript Nullish Coalescing Operator in JavaScript Comma Operator in JavaScript Typeof JavaScript Operator Precedence in JavaScript JavaScript if, else & nested if statement Switch Statement in JavaScript While & Do While Loops in JavaScript For Loop in JavaScript Break statement in JavaScript Continue Statement in JavaScript Arrays in JavaScript Array Constructor in Javascript Sparse Array Vs Dense Array in JavaScript How to merge Arrays in JavaScript Array Methods in JavaScript Functions in JavaScript Function Parameters & Arguments in JavaScript JavaScript Default Parameters Pass by Value and Pass by Reference in Javascript Function Expression in Javascript Nested Functions in JavaScript Immediately-invoked Function Expressions (IIFE) JavaScript Callback Functions Arrow Functions in JavaScript Arguments Object In JavaScript Rest Parameters in JavaScript Objects in Javascript Create Objects in JavaScript JavaScript Object Properties Computed Property Names in JavaScript Object Literal in JavaScript Constructor Function & New Operator in JavaScript Delete Operator in JavaScript hasOwnProperty in JavaScript Using Getters and Setters in Javascript DefineProperty in JavaScript JavaScript Property Descriptors Enumerable, Writable & Configurable Object Destructuring in JavaScript Variable Scope in JavaScript Hoisting in JavaScript Lexical Scope & Closures in JavaScript This in JavaScript Global Object, Window & Globalthis in JavaScript Call function in Javascript Prototype In Javascript Prototype Inheritance in JavaScript Instanceof Operator in JavaScript Spread Operator in JavaScript

Prototype Inheritance in JavaScript

The Javascript uses the Prototypes to implement the inheritance. In this tutorial, we will learn how to use Prototype to create Inheritance. Inheritance makes code reusable, readable & maintainable by sharing the instance of existing properties & methods across objects

What is Prototype Inheritance

Inheritance is a mechanism by which one object acquires the property and behavior of another object. In classical languages like C# & Java, this is done with classes.

But in Javascript, we do not have the concept of classes. JavasScript has only Objects. To implement inheritance JavaScript makes use of Prototype. The Inheritance is known as Prototype Inheritance.

Prototype Recap

A Prototype is just another JavaScript Object. The JavaScript assigns it to the [[Prototype]] property of the object when it creates it. The [[Prototype]] is the internal property and is hidden from us. This Property points to the Prototype Object or NULL.

Accessing the Prototype of an object

We cannot access the [[Prototype]] directly. But we can access it either by using the __proto__ property or using the getPrototypeOf method of the Object

The Prototype Chain

Prototype objects are just like any other Javascript object. Hence Even they also have prototype objects. We can traverse using an object’s prototype until we find null. This is referred to as prototype chain

The image below shows a Prototype chain in JavaScript.

At the bottom, we have John object, which has a [[Prototype]] property. It points to Foo object. The Foo object is the prototype of the John object.

The Prototype object can also have a Prototype Object. Boo is a Prototype of Foo. The Prototype chain usually ends with Object.prototype. The Prototype of Object.prototype is NULL.

Useful References

Need for Inheritance

First, let us understand why we need Inheritance in the first place.

Take a look at the following snippet. The constructor function Person defines two properties and one method sayHi.

            
var Person = function(firstName, lastName) {
  this.firstName=firstName
  this.lastName=lastName
 
  this.sayHi=function() {
    console.log(" Hello "+this.firstName+' '+this.lastName)
  }
}
 
                
        
    

We create two new objects (john & bill) from the Person function.

            
var john = new Person("John","Dyer")
john.sayHi();       //Hello John Dyer
 
 
var bill= new Person("Bill","Gates")
bill.sayHi();       //Hello Bill Gates
 
 
                
        
    

The code above works perfectly well. But we can make it better

The issue is with the sayHi method. Every time we create a new Person it also creates an instance of sayHi method in the Memory.

Useful References

If you happen to create many such Person objects, then it will also mean that you have many instances of sayHi occupying the memory.

The solution is to create a single instance of sayHi method and share it among all the objects created from the Person function.

This is where we make use of Prototype Inheritance.

            
console.log(person.__proto__=== Person.prototype);
//true
 
console.log(Person.prototype.__proto__=== Object.prototype);
//true
 
console.log(Object.prototype.__proto__);
//null  
 
                
        
    

The prototype chain looks something like this.

            
person => Person.prototype => Object.prototype => null  
 
                
        
    

Prototype Inheritance

Whenever we create a function, JavaScript adds an extra property prototype to the function. The prototype property is an object. We can refer to it using the <functionName>.prototype. In the case of Person function, it becomes Person.prototype.

Whenever we create a new object using a new operator from the Person Function, the Person.prototype becomes the Prototype of the newly created object.

In the code from the previous example, we make a small change. We remove the sayHi function from the Person function. We add it to the Person.prototype object.

Run the code, and you will see the same result as the previous one.

        
var Person = function (firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
};
 
Person.prototype.sayHi = function () {
  console.log(" Hello " + this.firstName + " " + this.lastName);
};
 
var john = new Person("John","Dyer")
console.log(john)
john.sayHi();
 
var bill= new Person("Bill","Gates")
console.log(bill)
bill.sayHi();
 
                
        
    

The sayHi method no longer belongs to the john or bill objects.

Useful References

But you will find them in the __proto__ property of both john & bill objects. Both these methods actually point to the Person.prototype object. You can use the === to check if they are equal.

        
console.log(john.__proto__ === Person.prototype)  
//true
 
console.log(bill.__proto__ === Person.prototype)
//true
 
                
        
    

We have only one instance of Person.prototype object in the memory. The prototype Property of the function point to it. The [[Prototype]] property of the john & bill objects also point to it.

But how did john.sayHi() & bill.sayHi() work if they did not contain the sayHi method.

One Prototype per object

An object can have only one Prototype. But it can become a Prototype of many other objects.

How Prototype Inheritance Works

When we ask for a property or method from an object, JavaScript tries to read the property from the object itself. If the object lacks the property, then JavaScript looks for the property in the prototype object. And if that prototype object also does not contain the property, then JavaScript looks in its prototype. This process continues until it reaches the Object.prototype. The prototype of Object.prototype is NULL. Hence the search stops there and returns the undefined value.

When we call john.sayHi(), The javascript searches for sayHi method in the john object. It does not find it there. So it looks for it in the __proto__ of john. The __proto__ of john points to Person.prototype. It finds the method there, hence executes it, and returns the result.

Useful References

Inheritance & Built-in Objects

JavaScript has several built-in or native Objects. The following tables show the list of built-in objects, with their corresponding prototypes.

Built in Object Corresponding Prototype
Object Object.prototype
Array Array.prototype
Function Function.prototype
String String.prototype
Number Number.prototype
Date Date.prototype
Boolean Boolean.prototype
BigInt BigInt.prototype
Symbol Symbol.prototype

Object.prototype

The Object() is a built-in constructor function. We can create new objects using it. All the objects that we create from it get the Object.prototype as their prototype

        
console.log(Object.prototype)
 
                
        
    

As you can see from the image, the Object.prototype defines few methods. The constructor property points to Object() Constructor function. Because Object.prototype is created from it.

There are properties like hasOwnProperty, IsPrototypeOf, propertyIsEnumerable, toLocalString, toString, valueOf, etc. Every object that inherits from the Object.prototype have access to these properties.

Useful References

The following example creates obj object using the Object constructor. It can access the hasOwnProperty because Object.prototype is its prototype

        
obj = new Object();
obj.name="Roger Mayer"
 
console.log(obj.hasOwnProperty("name"))
//true
 
 
                
        
    

You can verify it by creating the new object with null as its prototype as shown in the example below. Accessing the hasOwnProperty results in TypeError, becuase it is not present in its prototype chain.

        
obj2 = Object.create(null);
obj2.name="Roger Mayer"
 
console.log(obj2.hasOwnProperty("name"))
 
//Uncaught TypeError: obj2.hasOwnProperty is not a function
 
 
                
        
    

String.prototype

Similarly, when you create a new String object, the newly created objects will get String.prototype as their prototypes.

As you can see from the image, the String.prototype has many methods. Due to Prototype Inheritance, the newly created objects will have access to all these methods.

The prototype of String.prototype is Object.prototype. Hence the newly created object can also access the methods of Object.prototype

Useful References
        
var str = new String( "This is string" );
 
 
//str.__proto__            == String.prototype
//str.__proto__.__proto__  == Object.prototype
 
//str => String.prototype --> Object.prototype --> Null
 
 
                
        
    

Simple primitive types

Note that JavaScript has seven simple primitive types. They are string, boolean, number, BigInt, Symbol, null, and undefined. They are not objects.

But JavaScript creates an object wrapper around the primitive types. This enables us to use prototype methods of the String object on the primitive string.

        
let primString="hi"
let objString=new String("Hi")
 
console.log(primString)
console.log(objString)
 
 
 
                
        
    

A console.log of both will make the difference clear.

Useful References

But comparing the __proto__ of both results in true. You can also access all the methods of the String.prototype. When we call a property or method on a string primitive, JavaScript automatically coerces it to a String object. Hence it works.

        
console.log(primString.__proto__==objString.__proto__)
//true
 
//All methods of String.prototype still work on primitive strings. 
primString.slice(0,1)
//
 
 
 
                
        
    

Array.prototype

Similarly, Arrays inherit from Array.prototype

        
var arr = ['Ford', 'Chevrolet', 'Buick', 'Tesla'];
 
 
//arr.__proto__            == Array.prototype
//arr.__proto__.__proto__  == Object.prototype
 
//arr => Array.prototype --> Object.prototype --> Null
 
 
 
                
        
    

Creating objects with Prototype

Apart from the Object constructor function, there are other ways in which you can create an Object.

Objects Created with Literal Syntax

The following example creates person object using the object literal syntax. The objects created using the literal syntax gets the Object.prototype as its [[Prototype]]

         
var person = { name: "Bill Gates"};
 
//prototype chain
//person --> Object.prototype --> null
 
 
 
                
        
    

Objects from constructor functions

We looked at this in the above examples.

 
var Circle = function(radius) {
  this.radius=radius
}
 
Circle .prototype = {
   area: function () {
      return Math.PI * this.radius * this.radius;
   },
   circumference : function() {
      return 2 * Math.PI * this.radius
   },
}
 
var cir = new Circle (10)
 
//cir.__proto__            == Circle .prototype
//cir.__proto__.__proto__  == Object.prototype
 
//cir => Circle.prototype --> Object.prototype --> Null





With Object.create

Using Object.create method allows us to specify the prototype of the newly created object.

For Example, let us create an object obj1 using the literal syntax

 
var obj1 = {a: 1};
//
// obj1 ---> Object.prototype ---> null





In the following example, we use Object.create to create obj2 using the obj1 as prototype.

 
var obj2 = Object.create(obj1);
 
// obj2 ---> obj1 ---> Object.prototype ---> null





You can access the property of the obj1 from obj2 because it is its prototype.

 
console.log(obj2.a); 
 
// 1  inheritated from obj1





You can create an object without a prototype by Passing the Null as the argument.

 
Object.create(null).





Adding Property to Prototype

We can add or alter the Property or method of a Prototype object. These changes will immediately become visible in all of the objects that are based on that prototype

In the example below, we change the sayHi method midway through the program.

        

var Person = function (firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
};
 
Person.prototype.sayHi = function () {
  console.log(" Hello " + this.firstName + " " + this.lastName);
};
 
var john = new Person("John","Dyer")
john.sayHi();       //Hello John Dyer
 
var bill= new Person("Bill","Gates")
bill.sayHi();       //Hello Bill Gates
 
console.log("Change the method sayHi")
 
//We change the sayHI method here
//Return lastName+FirstName
 
Person.prototype.sayHi = function () {
  console.log(" Hello " + this.lastName + " " + this.firstName);
};
 
//Now both prints lastName+FirstName
 
john.sayHi();     //Hello Dyer John
bill.sayHi();     //Hello Gates Bill
 
                
        
    

Writing doesn’t use prototype

The Prototype inheritance works only for reading the Properties. Write/delete operations work directly with the object.

            

var Person = function (firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
};
 
Person.prototype.sayBye="Bye";
 
var john = new Person("John","Dyer")
var bill= new Person("Bill","Gates")
 
console.log(john.sayBye);   //Bye
 
console.log(bill.sayBye);   //Bye
 
//Writing Property
//This will create a new Property in the john object
//does not change the Person.prototype.sayBye
 
john.sayBye="Goodbye"
 
console.log(john.sayBye);   //Goodbye
console.log(bill.sayBye);   //Bye
                
        
    

Delete also do not use prototype

Similarly, the delete operator deletes the property from the object. But it will not traverse the prototype chain to delete the objects from the prototype

In the example, we delete the sayBye from john. A similar property exists in Person.prototype. It will not affect it.

            
var Person = function (firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
};
 
Person.prototype.sayBye="Bye";
 
var john = new Person("John","Dyer")
var bill= new Person("Bill","Gates")
 
console.log(john.sayBye);   //Bye
 
console.log(bill.sayBye);   //Bye
 
john.sayBye="Goodbye"
 
console.log(john.sayBye);   //Goodbye
console.log(bill.sayBye);   //Bye
 
//Deletes sayBye from john
delete john.sayBye            
 
console.log(john.sayBye);   //Bye
console.log(bill.sayBye);   //Bye
 
//sayBye already deleted. Hence does nothing
delete john.sayBye
 
 
console.log(john.sayBye);   //Bye
console.log(bill.sayBye);   //Bye
                
        
    

Create object using Constructor function

The prototype property of the function has a special purpose.

Whenever we create a new object from the function, the prototype property becomes the prototype of the newly created object. The prototype property is empty initially. but you can add properties and methods or even other objects.

Consider the following example of the Person constructor function. it will automatically come with the Person.prototype property.

Every object, that we create with the Person function will have the Person.prototype as their prototype. For Example both employee & customer object will get Person.prototype as their prototype.

            
var Person= function(name) {
  this.name=name
}
 
var employee = new Person("Aida Bugg");
var customer = new Person("Roger Mayer");
                
        
    

You can verify it by comparing their prototypes.

            
console.log(employee.__proto__=== Person.prototype);
 
console.log(customer.__proto__=== Person.prototype);