JavaScript supports Object-Oriented Programming (OOP) through objects, prototypes, and classes. ES6 introduced a cleaner class syntax, making OOP easier to understand and write. In this blog, I'll explain the four pillars of OOP and some useful class features in JavaScript.
1. Inheritance
Inheritance allows one class to reuse the properties and methods of another class.
Example:
class Animal {
eat() {
console.log("Eating");
}
}
class Dog extends Animal {}
const dog = new Dog();
dog.eat();
Since Dog extends Animal, it inherits the eat() method.
This helps us avoid writing the same code again.
2. Polymorphism
Polymorphism means one method can behave differently depending on the object that calls it.
In JavaScript, this is usually achieved by overriding a parent class method in a child class.
Example
class Animal {
speak() {
console.log("Animal makes a sound");
}
}
class Dog extends Animal {
speak() {
console.log("Dog barks");
}
}
class Cat extends Animal {
speak() {
console.log("Cat meows");
}
}
const dog = new Dog();
const cat = new Cat();
dog.speak();
cat.speak();
Output:
Dog barks
Cat meows
Here, all classes have the same speak() method, but each class provides its own implementation. This is called polymorphism.
3. Abstraction
Abstraction means showing only the necessary functionality and hiding the internal implementation.
For example, when we start a car, we only press the start button. We don't need to know how the engine, fuel system, and battery work internally.
JavaScript allows us to achieve abstraction using classes and private methods or private fields.
Example
class Car {
start() {
this.#checkFuel();
console.log("Car Started");
}
#checkFuel() {
console.log("Checking Fuel...");
}
}
const car = new Car();
car.start();
Output:
Checking Fuel...
Car Started
The user only calls start(). The internal method #checkFuel() remains hidden from outside the class. This makes the code easier to use and protects the internal implementation.
4. Static Members
Normally, we create an object before calling a method.
const obj = new Person();
But some methods belong to the class itself, not to its objects.
These are called static methods.
Example:
class MathUtil {
static add(a, b) {
return a + b;
}
}
console.log(MathUtil.add(5, 3));
Notice that we didn't create an object.
5. Getters and Setters
Getters and setters allow us to control how properties are read and updated.
Example:
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length >= 3) {
this._name = value;
}
}
}
This helps us validate data before updating it.
6. Encapsulation Using Closures
Encapsulation means hiding data so it cannot be changed directly.
Example:
function BankAccount() {
let balance = 1000;
return {
deposit(amount) {
balance += amount;
},
getBalance() {
return balance;
}
};
}
const account = BankAccount();
account.deposit(500);
console.log(account.getBalance());
The variable balance cannot be accessed directly from outside the function.
7. Private Fields (#field)
Modern JavaScript provides another way to hide data using private fields.
Example:
class BankAccount {
#balance = 1000;
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(500);
console.log(account.getBalance());
Trying to access:
account.#balance;
will cause an error because private fields can only be accessed inside the class.
Conclusion
Now I know that JavaScript's OOP system is built on prototypes, and classes simply make the syntax cleaner and easier to read. Understanding these concepts gives a strong foundation for writing better JavaScript code.
Top comments (1)
Hi Harshith, I might want to take a look at this post and format your code examples.