JavaScript - Object Oriented Programming
Object-Oriented Programming (OOP) in JavaScript is a programming paradigm that uses objects and classes to organize code and structure applications. It allows developers to create reusable, modular, and maintainable code by encapsulating data and behavior within objects. JavaScript is prototype-based procedural language, which means it supports both functional and object-oriented programming. This type of style allows the creation of an object without first defining its class.
What are Classes and Objects in JavaScript?
Class
A class is a blueprint or template for creating objects. It defines a set of properties and methods that the objects created from the class will have. It serves as a model to define the characteristics and behaviors that the objects will possess. A class does not represent any particular item but rather a concept or a group of similar items.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, ${this.name}`);
}
}
const person1 = new Person(‘Bob’, 25);
person1.greet(); // Output: Hello, Bob
a constructor function is a special type of function used to create and initialize objects. The primary purpose of a constructor function is to set up new objects with initial properties and values. When called with the new keyword, a constructor function creates a new object, sets its prototype, and returns the newly created object.
Object
An object is an instance of a class. It represents a specific entity that has the properties and behaviors defined by its class. Objects are used to interact with the actual data. They hold specific values for the properties defined by the class and can perform actions through the methods.
Example
// Defining a class named Person
class Person {
// The constructor method is called when a new instance is created
constructor(name, age) {
this.name = name; // Setting the instance’s name property
this.age = age; // Setting the instance’s age property
}
// Method to display the person’s details
displayDetails() {
console.log(`Name: ${this.name}, Age: ${this.age}`);
}
}
// Creating an instance of the Person class
const person1 = new Person(‘Alice’, 30);
// Accessing properties and methods
console.log(person1.name); // Output: “Alice”
console.log(person1.age); // Output: 30
person1.displayDetails(); // Output: “Name: Alice, Age: 30”
Principles of OOPS
1. Encapsulation
Encapsulation involves bundling the data (properties) and methods (functions) that operate on the data into a single unit, typically called a class. It also restricts direct access to some of the object’s components, which is a means of preventing unintended interference and misuse of data.
Example
class Person {
constructor(name, age) {
this.name = name; // Private property by convention
this.age = age;
}
getName() {
return this.name;
}
setName(name) {
this.name = name;
}
getAge() {
return this.age;
}
setAge(age) {
if (age > 0) {
this.age = age;
} else {
console.log(‘Age must be positive’);
}
}
}
const john = new Person(‘John’, 30);
console.log(john.getName()); // John
john.setAge(31);
console.log(john.getAge()); // 31
In this example, the properties name and age are encapsulated within the Person class, and can only be accessed or modified through the getter and setter methods.
2. Inheritance
Inheritance allows a class to inherit properties and methods from another class. This promotes code reusability.
Example
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog(‘Rex’);
dog.speak(); // Rex barks.
Here, the Dog class inherits from the Animal class and overrides the speak method.
The value of this in a class method always refers to the instance of the class when the method is called on an instance.
3. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common superclass. It is often expressed as the ability of different objects to respond to the same method in different ways.
Example
class Bird {
speak() {
console.log(‘Bird makes a sound.’);
}
}
class Parrot extends Bird {
speak() {
console.log(‘Parrot talks.’);
}
}
class Sparrow extends Bird {
speak() {
console.log(‘Sparrow chirps.’);
}
}
const birds = [new Bird(), new Parrot(), new Sparrow()];
birds.forEach(bird => bird.speak());
// Output:
Bird makes a sound.
Parrot talks.
Sparrow chirps.
In this example, different bird objects respond to the speak method in their own unique ways, demonstrating polymorphism.
4. Abstraction
Abstraction involves hiding complex implementation details and showing only the necessary features of an object. This can be achieved using classes and methods that provide a clear interface.
Example
class Vehicle {
start() {
console.log(‘Vehicle started’);
}
// Abstract method (not enforced but followed by convention)
fuelEfficiency() {
throw new Error(‘This method should be overridden’);
}
}
class Car extends Vehicle {
fuelEfficiency() {
console.log(‘Car has good fuel efficiency.’);
}
}
const myCar = new Car();
myCar.start(); // Vehicle started
myCar.fuelEfficiency(); // Car has good fuel efficiency.
Here, the Vehicle class provides a generic interface with the start method and an abstract fuelEfficiency method that should be implemented by subclasses like Car.
These principles help in organizing code in a more structured and intuitive way, making it easier to manage and extend.