Thursday, 13 May 2021

OOPS in JavaScript

JavaScript OOPS Concept

Classes : 

A class is simply a template for creating object. 

Classes are just special function. You can define class as you define function expression and function declaration.

Component of Class Syntax : 

1. Declaration

2. Expression 

 

Above is two ways to define a Class.

To define a class, 

 - Use class  keyword. 

Always add a method named constructor():

 

1. Class declaration : 

This is One way to define class 

Example : 

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

This Example creates a class named Rectangle. 

It has two initial properties : height and width.

 

Hoisting : 

An important differance between function declaration and class declaration is hoisting. 

Function declarations are hoisted while class declarations are not.

You first need to declare your class before accessing , otherwise code will throw an error. 

 

2. Class Expression :  

It is another way to define a class.  

It can be named or unnamed. 

The name is given like a variable. 

Example :

let Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

 

Though, name can be retrived using class' name property. Like, 

 console.log(Rectangle.name);

 

Constructor :

It is a special method for creating and initializing object. 

When an object of the class is declare, this method is called automatically. 

If constructor method is not defined, Javascript will add an empty one. 

 

Object : 

Like any other programming languages, Object in Javascript is a standalone entity. 

It can be compared with real-life object. 

Example : 

A mobile phone is an object. It has a RAM, processor, weight, material it is made of etc.

Similarlly, JavaScript objects can have properties, which define their characteristics/ properties. 

Access properties with simple dot nation. 

ObjectName.PropertyName 

 

There are different ways to create new objects : 

1. Using object literal - (for single object)

2. Using new  keyword. - (for single object)

3.Using Object constructor. - (for multiple object creation)

In ECMAScript 5, an object can also be created with the function Object.create().


 1. Using Object literal : 

It is a list  of  {name:value} pairs.

define and create object in one statement. 

 Example : 

var person = {firstName:"John", lastName:"Doe", age:20, weight:80};

//It can span mutilple lines. Brackets and spaces are not important. 

var person = {

firstName:"John", 

lastName:"Doe", 

age:20, 

weight:80 

};

 

2. Using new keyword : 

var person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.age = 20;
person.weight= 80;  

 

3. Using object constructor : 

Sometimes we need a "blueprint" for creating many objects of the same "type". Here object constructor function come into picture. 

Example : 

function Person(first, last, age, weight) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.weight= weight;
}

 Here, Person() is object constructor function. 

objects can be created by calling constructor function with new keyword.

var myFather = new Person("John", "Doe", 50,80);
var myMother = new Person("Emma", "Rally", 48, 60); 

 

this keyword : 

It is the object itself. 

It is the substitue for new object.

The value of this will become the new object when a new object is created.

 

Class Inheritance : 

Class inheritance is a way for one class to extend another class. 

We use extend  keyword to inherit child class from parent class. 

Let's say we have a class Bird

class Bird{
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  fly(speed) {
    this.speed = speed;
    alert(`${this.name} flies with speed ${this.speed}.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} stands still.`);
  }
}

let bird= new Bird("Sparrow");


  Now, let's represent this graphically.

Graphical representation of Class


Now, we would like to create another class 'Sparrow' .

As the sparrow is a bird, it can have access to bird methods. It can do what a 'generic' birds can. 

Let's inherit sparrow class from Bird. 

class Sparrow extends Bird{
  hide() {
    alert(`${this.name} hides!`);
  }
}

let sparrow= new Sparrow("White Sparrow");

sparrow.fly(5); // White sparrow fly with speed 5.
sparrow.hide(); // White sparrow hides!

 Object of Sparrow class have access to both class' (Bird and Sparrow) methods. 

i.e. sparrow class method- sparrow.hide()

    Bird class method - sparrow.fly()


Extend keyword works using old prototypes. It sets Sparrow.prototype.[[prototype]] to Bird.prototype

If  a method is not found in child class (Sparrow.prototype), JavaScript searches it in parent class (Bird.prototype).

Graphical representation of Inheritance

To find sparrow.fly() method, the engine uses bottom-up approach. 


1. The Sparrow object. (has no fly method )

2. prototype of sparrow object that is Sparrow.protype ( which has no fly() method but has hide() method)

3. prototype of it's parent that is Bird.protype (due to extend) (which has fly() method and it runs finally)

 

Learn more about inheritance here.  


Overriding : 

JavaScript only supports method Overriding, not overloading. 

If you use multiple function with the same name, last one will override previous one. 

1. Override default function : 


function alert(msg) 
{
   console.log(msg);
};
alert("This is an alert."); //it won't show alert box
                              like usually.It will now 
                              log the message in
                              console as we've 
                             Ioverride it.


2. Override previous definition of function : 

//Calculate area of rectangle
function calculateArea(x, y){
	return x*y;
}
function calculateArea(x){
	return x*x;
}
console.log("Area of rectangle 2x3 is : " + calculateArea(2, 3)); // answer : 4
console.log("Area of square 5x5 is : " + calculateArea(5)); // answer : 25

Here, we've override the function. So calculateArea(2,3) will now return 4 instead of 6.

 

3. Override parent class method. 

Suppose we've two class. Consider an above example of inheritance. 

Sparrow class is inherited from Bird class. Bird class has a method named fly() and Sparrow class a method called hide().

Now, if we want to change behaviour of fly() method in child class. This method in parent class alerts speed of a sparrow.

class Bird{
    constructor(name) {
    this.speed = 0;
    this.name = name;
  }
 
 fly(speed) {
    this.speed = speed;
    alert(`${this.name} flies with speed ${this.speed}.`);
  }
 
 stop() {
    this.speed = 0;
    alert(`${this.name} stands still.`);
  }
}

class Sparrow extends Bird{
 
    hide(){
        alert(`${this.name} hides!`);
    }
 
 
 //override parent class method fly()
    fly(speed){
        console.log('sparrow flies');
    }
}

let sparrow= new Sparrow("White Sparrow");

sparrow.fly(5); // sparrow flies
sparrow.hide(); // White sparrow hides!

Here, fly() method will just log the message in console. 

Now, call parent class' fly() method. 


class Bird{
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  fly(speed) {
    this.speed = speed;
    alert(`${this.name} flies with speed ${this.speed}.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} stands still.`);
  }
}

class Sparrow extends Bird{
 
  hide() {
      alert(`${this.name} hides!`);
  }
  //override parent class method fly()
  fly(speed){
 
     // call parent class' method fly() 
     // use super keyword to do so
 
    super.fly(5);
    console.log('sparrow flies');
  }
}
let sparrow= new Sparrow("White Sparrow");
sparrow.fly(5); // alert box - White sparrow flies with speed and  log message -
                  sparrow flies 
sparrow.hide(); // White sparrow hides!  

Changes is represented with blue line in above example when calling parent class' fly() method. 


Abstraction : 

Abstraction is a way of hiding implementaion details from user and showing only functionality to user. 

Let's have one Example : 

We want to calculate employee's total salary monthly : 

Total salary is : BaseSalary + monthlyBonus 


function Employee(name,age, baseSalary)
{
    this.name =name;
    this.age = age;
    this.baseSalary = baseSalary;
    this.monthlyBonus = 1000;
    this.calculateFinalSalary = function(){
        let finalSalary = this.baseSalary + this.monthlyBonus;
        console.log('Final Salary is : ' + finalSalary);
    }
    this.getEmpDetails = function(){
        console.log('Name : ' + this.name + ' | Age : ' + this.age)
    }
}
	
    let emp1 = new Employee('John', 30, 2000);
    emp1.getEmpDetails();
    emp1.monthlyBonus = 20000; // direct access to monthlybonus property 
    emp1.calculateFinalSalary(); // final salary will be 2000 + 20000 
                                    insted of  2000 + 1000
                                    due to direct access to monthlybonus property
 

To avoid this issue, abstraction comes into picture. 

use monthlybase as a varible. 

 Using abstraction :


function employee(name,age, baseSalary)
{
	this.name =name;
	this.age = age;
	this.baseSalary = baseSalary;
	let monthlyBonus = 1000;           // Take monthlyBonus as variable 
 
        let calculateFinalSalary = function(){
	    let finalSalary = baseSalary + monthlyBonus;
	    console.log('Final Salary is : ' + finalSalary);
	}
 
        //Call calculateFinalSalary function here.  
        this.getEmpDetails = function(){
	     console.log('Name : ' + this.name + ' | Age : ' + this.age)
             calculateFinalSalary();		                 
	}
}
	let emp2 = new employee('John', 30, 2000);
	emp2.getEmpDetails();         // final salary will be 2000 + 1000 = 3000 
                                         now as expected

 Learn in detail about abstraction here

This was all about JavaScript OOPS concepts. Thanks for reading:)

No comments:

Post a Comment