Object Oriented Programming in Javascript

Object Oriented Programming in Javascript

Let's start by knowing what Object Oriented Programming is -

In Object Oriented Programming we can classify languages into two types- Class-based and prototype-based languages.

Class-based OOP is about creating classes and objects that contain both properties and methods on the other hand prototype-based OOP explicitly excludes the concept of classes, and object inherits from other existing objects using the prototype.

In Javascript, we follow the prototype-based OOP.

WHAT IS PROTOTYPE-BASED OOP?

In Prototype-based object-oriented programming, classes are not explicitly defined. Inheritance is performed by reusing existing objects that serve as prototypes.

As there is no class concept in prototype-based object-oriented programming, we use a method of linking the prototypes, that is objects inherit properties and methods from the existing objects.

Now the question arises what is a prototype ??

A prototype is a built-in property [[Prototype]]. A prototype property is an object, where we can attach methods and properties in a prototype object, which enables all the other objects to inherit these methods and properties.

const Car = function (company, speed) {
  this.make = company;
  this.speed = speed;
};
console.dir(Car);

Car has a prototype property and that prototype property has a constructor object which again points to the Car constructor function.

Can add methods to the Prototype property in a function constructor which will be inherited by the different objects.

const Car = function (company, speed) {
  this.company = company;
  this.speed = speed;
};

Car.prototype.brake = function () {
  this.speed = this.speed - 5;
  console.log(this.speed);
};
console.dir(Car.prototype);

Prototype property enables other objects to inherit all the properties and methods of the function constructor.

When we create an object using the function constructor, JavaScript Engine will add __proto__ in the object which will point to the prototype’s constructor object. We can access the prototype of an object using the object. proto syntax. proto is the internal property of an object, pointing to its prototype.

Creating a object 'tesla' -

const tesla = new Car('Tesla', 130);
tesla.brake();

Output :

We can also check whether 'tesla' object __proto__ is same to the car prototype by -

console.log(tesla.__proto__ === Car.prototype); //Output: true

We can also set the prototype of an object using the proto .

Using __proto__ is the same thing as using the extends (used to Inherit parent class properties and methods in child class) keyword in OOP languages.

const EV = function(charge){
    this.charge = charge;
}
//set the prototype of Car
EV.__proto__ = Car;

//access the brake method
console.log(EV.brake());

PROTOTYPE INHERITANCE IN JAVASCRIPT-

We all have used prototype inheritance without knowing it for example, if you've used methods on functions like bind(), apply(), call() etc. If we go to the official documentation we will see Function.prototype.bind() because Function.prototype is a prototype of all function objects that we create in JavaScript.

PROTOTYPE CHAIN -

Whenever the __proto__ property points to an Object. That object will also have a prototype that will also point to another object. In effect, it creates a prototype chain. The prototype chain ends with an object that has a value of null. When a certain method(or property) is called, it first checks inside the object but when it doesn’t find it, the search moves to the Object’s prototype and continues the search in the chain till it finds the **proto :* null*.

HOW TO IMPLEMENT PROTOTYPE INHERITANCE IN JAVASCRIPT -

There are 3 ways to implement prototype inheritance in javascript -

  1. Constructor Function -

    We can create objects using the constructor functions, using this method only built-in objects like an array, map, set are implemented in javascript.

    In Javascript, a constructor is called when an object is created using a new keyword.

    The new operator does the following things -

    1. creates an empty object.

    2. this keyword in the constructor function call is set to the new object.

    3. the new object is linked ( proto property) to the constructor function prototype property.

//constructor function
const Student = function (name) {
  this.name = name;
  console.log(this);
}
//never add functions in constructor function
Student.prototype.printName = function () {
  console.log(this.name);
};

let ayushi = new Student('Ayushi');

Output -

We should never create a function inside of a constructor function because every time we create an object, functions inside the constructor function will also be created every time for each object which can cause slow performance.

  1. ES6 CLASSES-

    We can implement OOP using classes, but behind the scenes, it uses prototype inheritance.ES6 Classes are the modern and alternative way of implementing the constructor function for prototype inheritance. This was introduced to make it easy for developers to understand using class-based OOPs.

     class Student {
       constructor(name, id) {
         this.name = name;
         this.id = id;
         console.log(this);
       }
    
       printDetails() {
         console.log(this.name, this.id);
       }
     }
    
     const ayushi = new Student('Ayushi', 550);
    

    Output -

    Whenever we create an object of a class, a constructor function is invoked first. If there is no constructor, the default constructor is invoked.

  2. Object.create ( )-

    Object.create ( ) creates a new object and allows you to link the new object prototype to existing ones.

     const Student = {
       setdetails(name, id) {
         this.name = name;
         this.id = id;
       },
    
       printDetails() {
         console.log(this.name, this.id);
       },
     };
    
     let ayushi = Object.create(Student);
     ayushi.setdetails('Ayushi', 550);
     ayushi.printDetails();
    

    In Javascript, 4 basic principles of OOP ( Abstraction, Encapsulation, Inheritance & Polymorphism) also work differently I will share that in the next blog.

    Thank you for reading.