3 principles of OOP in JavaScript
Tags: javascript, beginners, typescript
Published: 2023-04-12 00:21:26

## Intro

As I always mention, I am reading a great book for TypeScript learners, [learning TypeScript](https://www.oreilly.com/library/view/learning-typescript/9781098110321/?_gl=1*afxut*_ga*NTE1MjkzMTQxLjE2Nzc4NzgwOTg.*_ga_092EL089CH*MTY3Nzg3ODA5OC4xLjEuMTY3Nzg3ODEwNS41My4wLjA.), for the sake of my goal of polishing the skills of TypeScript as a well-rounded Front-End Developer.

Last week, I have covered the chapter of Class in this book. It contained more than 30 pages and also I was required properly understand the concepts of class in JavaScript.

Since I have almost forgotten everything regarding the principles of JavaScript class in my mind, I have decided to relearn its basic concepts of it. In doing so, I have noticed that interpreting OOP (Object-Oriented Programming) correctly is essential as the first thing to do.

Then, in this article, I am going to dive into 3 must-know principles of OOP with simple words and JavaScript code samples so everyone can understand easily. So let's get into it!

## What is OOP in simple words?

First of all, OOP stands for "Object-Oriented Programming". OOP is the idea of using "Objects" to represent and interact with data. 

When managing data in OOP, we can utilize objects that are the instances of "Class", meaning blueprints for creating objects and containing properties and methods in it.

Class objects are reusable, able to inherit both properties and methods and allowed to keep the same methods but execute them differently by following the idea of Polymorphism.

Making use of class in OOP optimizes code structures that result in improving the modularity and readability of codes.

In order to understand the logic of OOP more, let's move on to the main topic of this article; 3 principles of OOP - Encapsulation, Inheritance, and Polymorphism!

**1. Encapsulation**

Encapsulation stands for creating a capsule that holds properties and methods inside to protect them from unexpected accesses from outside of it.

Encapsulation allows us to make code structures simple and easy to maintain to keep good maintainability of them. 

It also enables us to implement codes without exposing them outside of classes, which results in preventing bugs and errors.

Here is a simple code sample describing Encapsulation.

```typescript
// Declare a class whose name is Fruit
class Fruit {
  name: string;
  color: string;

  // Initialize properties of Fruit class
  constructor(name:　string,　color:　string) {
    this.name = name;
    this.color = color
  }

  // Declare a describeFruit method
  describeFruit() {
    console.log(`The color of ${this.name} is ${this.color}.`);
  }
}

const apple = new Fruit("Apple","red")

// We can access and implement properties and methods capsuled in Fruit class
console.log(apple.color) // Output: "red"
apple.describeFruit() // Output: "The color of Apple is red."

// When trying to access non-existing instances, TypeScript complains that and gives us an error 
console.log(apple.size) // Error: Property 'size' does not exist on type 'Fruit'.
```

**2. Inheritance**

Inheritance in OOP means the process of creating new classes that inherit one or more than one properties and methods from existing classes.

Inheritance contributes to reducing code lines because we do not have to write duplicated code every time a new value that inherits a parent class at all.

Here is a code snippet for the explanation of Inheritance.

```typescript
// Declare Parent class
class Parent {
    firstName: string;
    lastName: string;
    age: number;

    constructor(firstName:　string,　lastName:　string,　age:　number) {
        this.firstName = firstName
        this.lastName = lastName
        this.age = age
    }
    greeting() {
        console.log(`Hi, my name is ${this.firstName} ${this.lastName}, and I'm ${this.age} years old!`)
    }
}

// Define Child class that inherits Parent class
class Child extends Parent {
    // Type definition for the property that does not exist in Parent class
    isAbleToDrink: boolean

  constructor(firstName:　string,　lastName:　string,　age:　number,　isAbleToDrink:　boolean) {
        // super is a special keyword referring to instances that extended class has
        super(firstName,　lastName,　age);
        this.isAbleToDrink = isAbleToDrink;
    }
    buyBeverage() {
        console.log(this.isAbleToDrink ? `${this.firstName} can buy a Coke` : `${this.firstName} can a glass of beer`)
    }
}

const dad = new Parent("Mike", "Trout",32)
console.log(dad.age) // Output: 32
dad.greeting() // Output: "Hi, my name is Mike Trout, and I'm 32 years old!"

const son = new Child('John', 'Trout',12, false);
console.log(son.isAbleToDrink) // Output: false

// Thanks to inheritance, we can access the method that is defined in Parent class
son.greeting() // Output: "Hi, my name is John Trout, and I'm 12 years old!"
son.buyBeverage() // Output: "John can buy a Coke"
```

**3. Polymorphism**

Polymorphism is the feature allowing objects to take multiple different forms respectively.

In other words, child classes that inherit methods from parent classes still can implement them with the same names but differently. 

This principle allows us to have some flexibility in child classes especially the results of methods are depending on codes written in them respectively.

This code example below illustrates the concept of Polymorphism in saySomthing method.

```typescript
// Declare Animal class as the parent class
class Animal {
  nickname:string;

  constructor(nickname:string) {
    this.nickname = nickname;
  }

  saySomething() {
    console.log(`${this.nickname} says something.`);
  }
}

// Each sub class (Dog, Cat, and Cow) has same method (saySomething) as Animal class has but outputs from it are different respectively
class Dog extends Animal {
  saySomething() {
    console.log(`${this.nickname} barks.`);
  }
}

class Cat extends Animal {
  saySomething() {
    console.log(`${this.nickname} meows.`);
  }
}

class Cow extends Animal {
  saySomething() {
    console.log(`${this.nickname} moos.`);
  }
}

new Dog("Zoy").saySomething() // Output: "Zoy barks."
new Cat("Mike").saySomething() // Output: "Mike meows."
new Cow("John").saySomething() // Output: "John moos."
```

## Conclusion

3 concepts of OOP (Encapsulation, Inheritance, and Polymorphism) are definitely vital for improving your understanding of class in JavaScript (as well as other Object-Oriented Programming languages) and for empowering the performances of your code by applying JavaScript classes.

Actually, I am still not 100% comfortable with using class in JavaScript for my real projects. 

Thus, the next step for me is to introduce class to one of my personal projects with TypeScript to understand it more, including a better understanding of 3 principles of OOP.

## References

- [Learning TypeScript](https://www.oreilly.com/library/view/learning-typescript/9781098110321/?_gl=1*afxut*_ga*NTE1MjkzMTQxLjE2Nzc4NzgwOTg.*_ga_092EL089CH*MTY3Nzg3ODA5OC4xLjEuMTY3Nzg3ODEwNS41My4wLjA.)
- [Object-oriented concepts as explained to a 6-year-old](https://www.educative.io/answers/object-oriented-concepts-as-explained-to-a-6-year-old)
- [The basics of Object-Oriented Programming (simple definition)](https://funtech.co.uk/latest/explain-object-oriented-programming-to-kids#:~:text=What%20is%20OOP%20in%20simple%20words%3F,its%20own%20procedures%20or%20methods.)