Object Oriented JavaScript- A Guide for JavaScript Developers
What is OOP?
Object-oriented programming is a model for software development centered around objects. Erlier we don’t have this we are depend on the procedural language like C. What problem with procedural language that we have to achieve things in steps but once your project get bigger then it is very hard to understand and also maintain the code.
Here’s a breakdown of key OOP concepts relevant to JS:
Objects: Fundamental entities that hold properties and methods. Objects are created using object literals ({}) or constructor functions.
Classes (ECMAScript 2015+): Blueprints that define the properties and methods shared by objects of a particular type. Classes offer a more concise way to write code that achieves the same results as the underlying prototype-based system.
Properties: Data attributes associated with an object. They represent the object’s characteristics.
Methods: Functions attached to objects that define their behavior. Methods operate on the object’s data.
Inheritance: Inheritance is a core concept of Object-Oriented Programming (OOP) that allows a class to inherit properties and methods from another class, called the superclass or parent class. The class that inherits from the superclass is called the subclass or child class..
Encapsulation: Practice of bundling data and methods together within an object, potentially restricting direct access to internal properties. This promotes data integrity and controlled modification.
Polymorphism: Ability of objects of different classes to respond to the same method call in distinct ways. This allows for flexible and dynamic interactions.
Classes in JavaScript
ECMAScript 2015 (ES6) introduced the class
keyword, providing a more familiar syntax for those accustomed to class-based OOP. While classes in JavaScript offer a convenient way to write code, it’s essential to understand that they ultimately translate to prototype-based inheritance. Under the hood, they still make use of the prototype chain.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hi, my name is: ${this.name}`);
}
const person = new Person('Shivam', 24);
person.greet(); // Output: Hi, my name is: Shivam
}
Classes offer a cleaner syntax for defining object properties and methods, making code more readable and maintainable, especially for developers coming from class-based languages.
Inheritance
Inheritance is a core concept of Object-Oriented Programming (OOP) that allows a class to inherit properties and methods from another class, called the superclass or parent class. The class that inherits from the superclass is called the subclass or child class. JavaScript supports prototype-based inheritance, where objects inherit properties and methods from their prototype. The prototype is an object that is shared among all instances of a class.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Employee extends Person {
constructor(name, age, salary) {
super(name, age); // Call superclass constructor
this.salary = salary;
}
}
// Usage
const employee1 = new Employee("Bob", 30, 50000);
console.log(employee1.name, employee1.age, employee1.salary); // Outputs: "Bob 30 50000"
This code snippet demonstrates inheritance in JS. Let’s break it down:
Person Class: This class defines the basic properties (
name
andage
) for allPerson
objects.Employee Class: This class inherits from the
Person
class using theextends
keyword. It adds a new property(salary)
specific to employees.Employee Constructor: The
Employee
constructor calls thesuper
constructor (super(name, age))
to initialize the inherited properties fromPerson
. Then, it assigns thesalary
property.
Now, you can create Employee
objects that inherit properties from Person
(like name
and age
) and add their own property (salary)
.
Encapsulation
Encapsulation refers to the practice of bundling data and methods that operate on that data within a single unit called a class.
In encapsulation, the data and methods are defined in such a way that they are accessed only through the methods of the class, and not directly. This allows the class to have control over the data and how it is accessed, ensuring that it is used in the correct way.
JS doesn’t have strict mechanisms for enforcing encapsulation like private properties in other languages. However, there are conventions to achieve a similar effect:
Variable Naming: Use private member variables by prefixing them with an underscore (_). This discourages direct modification from outside the object.
Getter and Setter Methods: Define methods to access and modify private properties. These methods can perform validation or additional logic before retrieving or setting the value.
class Car {
constructor(model) {
this._model = model; // Private property
}
get model() {
return this._model;
}
set model(newModel) {
if (newModel.length < 3) {
throw new Error("Model name must be at least 3 characters long");
}
this._model = newModel;
}
}
const car1 = new Car("Camaro");
console.log(car1.model); // Outputs: "Camaro"
// Attempting to directly modify _model throws an error
car1._model = "Short"; // throws Error
In this example, the _model
property is private. The model
getter and setter methods provide controlled access and validation for the model name.
Another Example
In JavaScript, encapsulation can be achieved using closures, modules, and classes.
class Person {
constructor(name, age) {
let _name = name;
let _age = age;
this.getName = function() {
return _name;
}
this.getAge = function() {
return _age;
}
this.setName = function(name) {
_name = name;
}
this.setAge = function(age) {
_age = age;
}
}
}
let john = new Person("John", 30);
console.log(john.getName()); // Output: John
console.log(john.getAge()); // Output: 30
john.setName("James");
john.setAge(35);
console.log(john.getName()); // Output: James
console.log(john.getAge()); // Output: 35
In this example, the Person class uses closures to encapsulate the name and age properties and provides getter and setter methods to access and modify them. The implementation details of the object are hidden from the outside world, and only the necessary interfaces are exposed.
Polymorphism
Polymorphism is another core concept of Object-Oriented Programming that allows objects of different classes to be treated as if they are of the same class. In other words, it is the ability of an object to take on multiple forms.
Polymorphism is a principle that allows objects of different types to be treated as if they were the same type. In JavaScript, polymorphism can be achieved using function overloading, duck typing, and interface implementation.
Here’s a demonstration using function overriding:
class Animal {
makeSound() {
console.log("Generic animal sound");
}
}
class Dog extends Animal {
makeSound() {
console.log("Woof!");
}
}
class Cat extends Animal {
makeSound() {
console.log("Meow!");
}
}
const animal1 = new Dog();
const animal2 = new Cat();
animal1.makeSound(); // Outputs: "Woof!"
animal2.makeSound(); // Outputs: "Meow!"
Conclusion:
Inheritance, encapsulation, and polymorphism are essential OOP principles that can help developers create efficient and maintainable programs. JavaScript supports these principles through prototype-based inheritance, closures, modules, classes, function overloading, duck typing, and interface implementation. By mastering these principles, developers can create powerful and flexible programs that are easy to maintain and extend.