OOP in JavaScript

Internship at OpenGenus

Get this book -> Problems on Array: For Interviews and Competitive Programming

In this article, we will talk about Object Oriented Programming (OOP) in JavaScript and have covered different ideas like Inheritance, Encapsulation, Design Patterns and much more.

Table of contents

  1. Introduction of OOP in javascript
  2. objects in javascript
  3. class in javascript
  4. Encapsulation and inheritance in javascript
  5. Design patterns in javascript

INTRODUCTION OF OOP IN JAVASCRIPT

Javascript is a language used to add interactive features to our webpages built using html and css. And OOP in javascript can be achieved by creating classes which also provides diffrent yet simple ways of creating prototypes and organizing related data.

OBJECTS IN JAVASCRIPT

objects are unique entity which contains property and methods like let's take an example Dog , it is an object which have properties breed , color, size , strength etc.

Different ways of creating objects in javascript

1. creating object with help of constructor.

Constructor in javascript is used to create an object and set values if there are any object properties present. With the use of constructor new objects can be created using "new" keyword.

So, in this method we declare a function dog similar to class passing four parameters breed , color , size , strength ( the this keyword is used to differentiate the breed,color,size , strength of the class to the breed ,color ,size, strength of the arguments that are being supplied.).We then simple create an object obj of the Dog, initialize it and call it’s method.

//Dog function
function dog(breed,color,size,strength){
    this.breed = breed;
    this.color = color;
    this.size = size;
    this.strength = strength;
}
//new keyword to create an object
const myDog  = new dog('pug','wheat','3 feet','medium');
//property accessors
console.log(myDog.breed);
console.log(myDog.color);
console.log(myDog.size);
console.log(myDog.strength);

OUTPUT

pug
wheat
3 feet
medium

2. Using Object Literal

Literal are used to define objects and its properties inside the curly braces.
In the code below we are creating a simple object named dog with the help of object literal,having properties like breed,color,size.Then we make use of the property accessor methods(i.e Dot notation,Bracket notation) to print the values in the console. And than we added a property called name also to the object.

//creating js objects with object literal
let dog = {
    breed : 'pug',
    color : 'wheat',
    size : '3 feet'
};
//accesing properties
console.log(dog.breed); //dot notation
console.log(dog['size']); //bracket notation
//adding property
dog.name = 'vodafone Dog';
console.log(dog);

OUTPUT

pug
3 feet
{ breed: 'pug',
  color: 'wheat',
  size: '3 feet',
  name: 'vodafone Dog' }

3. Creating object with Object.create() method:

The Object.create() method creates a new object, using an existing object as the prototype of the newly created object.

const Anime = {
    watched : false,
    printStatus : function(){
        console.log(`Anime name is ${this.name}. And I have watched it?: ${this.watched}`);
    }
};
// using object.create methode
const me = Object.create(Anime);
me.name = 'Jujutsu Kaisen';
me.watched = true;
me.printStatus();

OUTPUT

Anime name is Jujutsu Kaisen. And I have watched it?: true

CLASS IN JAVASCRIPT

class - It is a user-defined template where it stores objects, a class can store multiple objects.

One thing to note here is that there is no classes in JavaScript we have only Object. To be more precise, JavaScript is a prototype based object oriented language, which means it doesn’t have classes rather it define behaviors using constructor function and then reuse it using the prototype(check the implementation of it above).

Here we will be using ES6 classes and it's way of defining Object and simulating them as classes.

// Defining class using es6
class Dog {
constructor(name, color, size) {
	this.name = name;
	this.color = color;
	this.size = size
}
// a function inside a class
getDetails(){
	return (`The name of the Dog is ${this.name}.`)
}
}
// Making object with the help of the constructor
const dogA = new Dog('shero', 'white', 'small');
const dogB = new Dog('shishimanu', 'yellow', 'medium');

console.log(dogA.name); // shero
console.log(dogB.color); // shishimanu
console.log(dogA.getDetails());// function call
console.log(dogB.getDetails());

OUTPUT

shero
yellow
The name of the Dog is shero.
The name of the Dog is shishimanu.

ENCAPSULATION AND INHERITENCE

Encapsulation is basically wrapping up of code into single logical unit.
In the below example we will see that we trying to put all the logic of getting friends , hobbys as well as displaying them under same class Person. and if we look closely we created a new object me and are working with an objects interface without considering the implementation details.

//encapsulation example

class person{
	constructor(name,age){
		this.name = name;
		this.age = age;
	}
	add_friends(friend){
		this.friend = friend;
	}
    add_hobbies(hobby)
    {
         this.hobby =hobby;
    }
	getDetails(){
		console.log(`Name is ${this.name},school is: ${this.friend} and hobbies are ${this.hobby}`);
	}
}

const me = new person('Mikasa',20);
me.add_friends('Aarmin')
me.add_hobbies('Being Awesome');
me.getDetails();

OUTPUT

Name is Mikasa,school is: Aarmin and hobbies are: Being Awesome

Inheritance

It is a property which allows us to inherits properties of super class to sub class. Inheritance is one of the most important feature of Object Oriented Programming.
Sub Class: The class that inherits properties from another class is called Sub class or Derived Class.

Super Class:The class whose properties are inherited by sub class is called Base Class or Super class. In the below code person is the parent class or the super class who's properties are inherited to the base class student (i.e name and id).

//Inhertiance example

class person{
	constructor(name){
		this.name = name;
	}
	//method to return the name string
	toString(){
		return (`Name of person: ${this.name}`);
	}
}
class student extends person{
	constructor(name,id){
		//super keyword to for calling above class constructor
        // inheriting properties of super class.
		super(name);
		this.id = id;
	}
    // method to return the id string
	toString(){
		return (`${super.toString()},Student ID: ${this.id}`);
	}
}
// creating object of sub class class
const student1 = new student('Itadori',20);
console.log(student1.toString());
// creating object of super class
const person1 =new person('Gojo');
console.log(person1.toString());

OUTPUT

Name of person: Itadori,Student ID: 20
Name of person: Gojo

DESIGN PATTERNS IN JAVASCRIPT

Some major advantages of using design patterns include project maintainability and also cuts off unnecessary work on the development cycle.

1. Constructor Design Pattern.

This is a special method that is used to initialize the newly created objects once a memory is allocated. New objeccts are created using "new"keyword.

var newObject = {};
//This creates a new empty Object with Object.create method
var newObject = Object.create(Object.prototype);
var newObject = newObject();

2.Prototype pattern

One can also say prototype pattern as a blueprint for each object created by the constructor.It is based on prototypical inheritance whereby objects created to act as prototypes for other objects.In the example below you can see that Watched funtion is a prototype of update function.

var myList= {
name:"Haikyu",
Watched:function(){
console.log("I have finished watching it");
}
Update : function (){
console.log ( "Update myList")
}
}
// object is created using object.create method
var myAnime= object.create(myList);
//You can now see that one is a prototype of the other
console.log (myAnime.name);]

3. Module Design Pattern

It is an advancement of prototype pattern ,there are diffrent types of modifiers (both private and public) and are set in the module pattern. One can create similar functions or properties without conflicts. There is the flexibility in renaming functions publicly but it does'nt allow to override(like you cannot change the function defination) the created functions from the outside environment.

function AnimalContainter () {

const container = [];

function addAnimal (name) {
container.push(name);
}

function getAllAnimals() {
return container;
}

function removeAnimal(name) {
const index = container.indexOf(name);
if(index < 1) {
throw new Error('Animal not found in container');
}
container.splice(index, 1)
}

return {
add: addAnimal,
get: getAllAnimals,
remove: removeAnimal
}
}

const container = AnimalContainter();
container.add('Hen');
container.add('Goat');
container.add('Sheep');

console.log(container.get()) //Array(3) ["Hen", "Goat", "Sheep"]
container.remove('Sheep')
console.log(container.get()); //Array(2) ["Hen", "Goat"]

4. SingleTon pattern

The Singleton object is implemented as an immediate anonymous function. The function executes immediately by wrapping it in brackets followed by two additional brackets. It is called anonymous because it doesn't have a name. In the below code you can see that a return function is created inside a fucntion which returns the value.

var Singleton = (function () {
    var instance;
    function createInstance() {
        var object = new Object("I am the instance");
        return object;
    }
    // var instance is implemented and used as an immediate anonymous function
    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();
function run() {

    var instance1 = Singleton.getInstance();
    var instance2 = Singleton.getInstance();
    console.log("Same instance? " + (instance1 === instance2));
}

OUTPUT

Same instance? true

5. Factory pattern

It provides a generic interface for creating objects, where we can specify the type of factory objects to be created. Therefore, we only specify the object and the factory instantiates and returns it for us to use.

It is wise for us to use factory pattern when the object component set up has a high level of complexity and when we want to create different instances of objects easily depending on the environment we are in.

One can also use factory pattern when working with many small objects sharing the same properties and when composing objects that need decoupling.

6. Observer Pattern

In this design pattern objects communicate with other set of objects simultaneously. No unnecessary push/pull of events is seen across the state instead the modules involved only modify the current state of data.

7. Command Pattern

The command design pattern encapsulates method invocation, operations, or requests into a single object so that we can pass method calls at our discretion.These commands are presented in run() and execute() format.

Encapsulating is basically wrapping up of data in single logic unit here in the below code we are trying to wrap the logic information requested , marking attendence and arranging are done under a same function block for the student variable.

In the code below

(function(){

var Student = {

//information requested
requestInfo: function( Name, rollNo ){
return "The information for " + Name + " with rollNo " + rollNo + " is foo bar";
},

// now Mark his/her attendence
markAttendence: function( name, rollNo ){
return "You are marking the attendence of  " + rollNo + name;
},

// now arrange the records
arrangeRecords: function( name, rollNo ){
return "You have successfully arranged the register" + name + " ( " + rollNo + " ) ";
}
};
})();

With this article at OpenGenus, you can start with oops in JavaScript having a basic idea about how objects and classes are created and how one can use it for code optimization.