Object-Oriented Programming in Javascript (ES6)

Object-Oriented Programming in Javascript (ES6)

OOP in Javascript ES6 | Abstraction, Inheritance, Encapsulation & Polymorphism

Introduction

Javascript is a multi-paradigm language it doesn't reinforce the concepts like other languages Java or C#, it means that we can incorporate the OOP paradigm if we want or we can just make things work with plain javascript objects.

In ES5 we have objects and we can make methods or inherit one object with another with the help of prototyping but this seems difficult to understand and implement so in ES6 we have classes that just work like in any other language, let's take a look at this.

Instantiate a class

In JS we have a class keyword and after that, you can give your class a name. Now you can object with this class like below:

class User {}

const user = new User();

Constructors

constructor is like a normal function every class have, whenever the class makes its object the constructor function is called, you can also pass parameters through constructor

class User {
  constructor(nema, email, age) {
    this.name = name;
    this.email = email;
    this.age = age;
  }
}

const user1 = new User('Huzaifa', 'huzaifa@gmail.com', 24);
const user2 = new User('ali', 'ali@gmail.com', 22);

Methods in Class

The functions in Classes are called methods, and call that methods through their objects, like below:

class User {
  constructor(nema, email, age) {
    this.name = name;
    this.email = email;
    this.age = age;
  }

  getAge() {
    return `User age is ${this.age}`;
  }
}

const user1 = new User('Huzaifa', 'huzaifa@gmail.com', 24);
const user2 = new User('ali', 'ali@gmail.com', 22);

console.log(user1.getAge()); // User age is 24
console.log(user2.getAge()); // User age is 22

4 Pillars of Object-Oriented Programming,

  1. Abstraction
  2. Encapsulation
  3. Inheritance
  4. Polymorphism

Now we will see all these pillars with their code implementation.

Abstraction

Abstraction is a concept in which we hide the implementation detail of a method and only expose the important things or attributes to the user, like in the code below.

We have two methods learnSkill and isEligibleForVote,

  • The first method is just updating the skills array.
  • The second method is checking either the user is eligible for vote.
class User {
  constructor(name, email, age) {
    this._name = name;
    this._email = email;
    this._age = age;
    this._skills = [];
  }

  learnSkill(skill) {
    this._skills.push(skill);
  }

  isEligibleForVote() {
    return this._age >= 18;
  }
}

const user = new User('Huzaifa', 'huzaifa@gmail.com', 24);

user.learnSkill('react');
user.learnSkill('javascript');

console.log(user._skills); // ['react', 'javascript']
console.log(user.isEligibleForVote()); // true

The user shouldn't concern about the methods implementation detail and just use them in their code.

Encapsulation

Encapsulation is a concept the variables or data in classes cannot be access directly from an object and should be private, there should be getter and setter methods to do this like below:

class User {
  constructor(name, email, age) {
    this._name = name;
    this._email = email;
    this._age = age;
  }

  get name() {
    return this._name;
  }

  set name(newName) {
    this._name = newName;
  }

  getAge() {
    return `User age is ${this.age}`;
  }
}

const user = new User('Huzaifa', 'huzaifa@gmail.com', 24);

console.log(user.name); // Huzaifa

user.name = 'Ali';

console.log(user.name); // Ali

Here we have getter and setter method for name variable.

Inheritance

Inheritance is a concept in which we can extend our parent class to child class for example, if there is a class named Animal and second class Duck so the class Duck can be inherited from Animal class, like below we have Developer class which is inherited from the User class, and now the Developer class can use its parent class User it's variable and methods.

Note: Here we have this super method in the child class which uses to gain access to its parent class.

class User {
  constructor(name, email, age) {
    this.name = name;
    this.email = email;
    this.age = age;
  }

  getAge() {
    return `User age is ${this.age}`;
  }
}

class Developer extends User {
  constructor(name, email, age, skills) {
    super(name, email, age);
    this.skills = skills;
  }
}

const developer = new Developer('Ali', 'ali@gmail.com', 22, [
  'html',
  'css',
  'js',
]);

console.log(developer.getAge()); //User age is 22
console.log(developer.skills); //['html','css','js']

Polymorphism

Polymorphism is also known as Method Overriding in some languages, this means that if the class is inherited from its parent class and both have the same methods, so the child class methods can be overridden or rewritten according to its functionality, like below we have same methods makeSound in different but inherited classes but their implementation detail is different according to their functionality they should perform.

class Animal {
  makesSound() {
    console.log('Animal makes sound');
  }
}

class Duck extends Animal {
  makesSound() {
    console.log('Quack Quack');
  }
}

class Cat extends Animal {
  makesSound() {
    console.log('meow meow');
  }
}

const cat = new Cat();
cat.makesSound() // meow meow

const duck = new Duck();
duck.makesSound() // Quack Quack

Full Tutorial