Definition: Procedural Programming is a programming paradigm based on the concept of procedures (functions) that operate on data. Code is organized into a sequence of steps or instructions.
Key Points:
Syntax Example:
// Procedural Programming Example
function calculateArea(length, width) {
return length * width;
}
let area = calculateArea(5, 10);
console.log("Area:", area); // Output: Area: 50
Explanation: All logic is inside one function; we pass data and get the result. No objects or data hiding. This approach works well for simple calculations but becomes messy as complexity grows, as there's no way to group related data and functions together.
Definition: Functional Programming treats functions as first-class citizens. Functions are pure, avoid changing state, and return new data instead of modifying existing data.
Key Points:
Syntax Example:
// Functional Programming Example
const add = (a, b) => a + b;
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2); // Creates new array without mutating original
console.log("Doubled:", doubled); // Output: Doubled: [2, 4, 6, 8, 10]
Explanation: Functions are independent and don’t depend on external data — ensuring reusability and predictability. In JS, methods like map, filter, and reduce embody this paradigm, making array manipulations declarative and concise.
Definition: OOP organizes code into objects that combine data (properties) and behavior (methods). It makes code modular, reusable, and easier to manage. JavaScript's OOP is prototypal, where objects inherit directly from other objects, but ES6 classes simplify this with familiar syntax.
Key Points:
Syntax Example:
// Object-Oriented Programming Example
class Student {
constructor(name, course) {
this.name = name;
this.course = course;
}
study() {
console.log(`${this.name} is studying ${this.course}`);
}
}
const s1 = new Student("Sudhanshu", "BCA");
s1.study(); // Output: Sudhanshu is studying BCA
Explanation: We create a Student class and make objects from it using new. This encapsulates data (name, course) and behavior (study()) into a single unit, promoting better organization than procedural or functional styles alone. Under the hood, JS uses prototypes for sharing methods efficiently.
The four core pillars of OOP provide the foundation for designing robust, maintainable software. Each pillar addresses specific challenges in code organization and extensibility.
Key Points with Definitions:
Explanation: This protects an object's internal state from unauthorized access, like a capsule that keeps medicine safe. In JS, use #privateField or closures for privacy.
Explanation: Users interact with simple methods without knowing the underlying complexity, like driving a car without understanding the engine. In JS, getters/setters abstract property access.
Explanation: Child classes inherit properties and methods, allowing specialization (e.g., a "SportsCar" extending "Car"). JS uses extends and super() for this.
Explanation: Enables flexibility, like calling draw() on various shapes—each draws itself uniquely. In JS, achieved via method overriding.
// Example of OOP Pillars
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, I am ${this.name}`);
}
}
class Student extends Person { // Inheritance
constructor(name, course) {
super(name);
this.course = course;
}
greet() { // Polymorphism
console.log(`Hi, I am ${this.name}, studying ${this.course}`);
}
}
const s2 = new Student("Himanshu", "CS");
s2.greet(); // Output: Hi, I am Himanshu, studying CS
Explanation: Student inherits from Person (inheritance), but overrides greet() (polymorphism). Properties are bundled (encapsulation), and users see only greet() (abstraction).
Definition: Constructor functions were used before ES6 classes to create objects. They are regular functions invoked with new, setting up object properties via this. Methods are added to the prototype for sharing across instances.
Key Points:
prototype are shared, saving memory.new binds this to a new object.
function Student(name, course) {
this.name = name;
this.course = course;
}
Student.prototype.study = function() {
console.log(`${this.name} is studying ${this.course}`);
};
const s3 = new Student("Ravi", "IT");
s3.study(); // Output: Ravi is studying IT
Explanation: This mimics class behavior: the function acts as a blueprint, and prototype enables inheritance. It's still valid today but classes provide cleaner syntax. Note how study is shared via prototype, not duplicated per instance.
Definition: Polymorphism allows a single interface to represent different underlying forms (data types). In practice, it lets us call the same method on different objects, with each responding in its own way.
Key Points:
class Shape {
area() {
return 0;
}
}
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
area() {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
area() {
return this.width * this.height;
}
}
const shapes = [new Circle(3), new Rectangle(4, 5)];
shapes.forEach(shape => console.log("Area:", shape.area()));
// Output: Area: 28.274333882308138 (approx for circle)
// Area: 20
Explanation: Both Circle and Rectangle override area() from Shape, allowing a loop to treat them polymorphically without knowing their exact type. This demonstrates runtime flexibility.
this Keyword?Definition: The this keyword refers to the current object in which the code is executing. It depends on where and how it is called—context is determined by invocation, not definition.
Key Points:
this—inherits from enclosing scope.window (non-strict) or undefined (strict).call(), apply(), or bind() to set this.
function getAgeYear() {
return new Date().getFullYear() - this.age;
}
function createUser(firstName, lastName, age) {
return {
firstName,
lastName,
age,
getAgeYear,
};
}
const user1 = createUser("Sudhanshu", "Kumar", 20);
const user2 = createUser("Himanshu", "Kumar", 19);
console.log(user1.getAgeYear()); // Output: 2005 (2025 - 20)
console.log(user2.getAgeYear()); // Output: 2006 (2025 - 19)
Explanation: Here, this refers to each user object, so this.age accesses each user's age. This dynamic binding is key to OOP in JS, enabling methods to operate on instance data seamlessly. Be cautious with callbacks, where this might lose context—use arrows or bind to preserve it.
new Keyword?Definition: The new keyword creates a new object from a constructor function or class. It performs four steps: creates an empty object, links its prototype, sets this to it, and returns it.
Key Points:
{} object.__proto__ to constructor's prototype.this inside constructor to the new object.new: Constructor runs but this is global—avoid this mistake.
class Car {
constructor(name, model) {
this.name = name;
this.model = model;
}
info() {
console.log(`${this.name} model is ${this.model}`);
}
}
const car1 = new Car("Tesla", "Model S");
car1.info(); // Output: Tesla model is Model S
Explanation: The new keyword automatically creates a new object, sets this to that object, and returns it. This is essential for instantiation in OOP. Forgetting new leads to errors, as properties would attach to the global object instead.
Definition: A class is a blueprint for creating objects with properties and methods. Introduced in ES6, it's syntactic sugar over constructor functions and prototypes, making OOP more intuitive.
Key Points:
class Name { constructor() {} methods() {} }.# prefix for true privacy (ES2022+).
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
showInfo() {
console.log(`Name: ${this.name}, Email: ${this.email}`);
}
}
const u1 = new User("Sudhanshu", "sudhanshu@example.com");
u1.showInfo(); // Output: Name: Sudhanshu, Email: sudhanshu@example.com
Explanation: Classes provide a clean template for objects. Here, User defines instance properties in constructor and a method showInfo. Extend it with extends for hierarchies. Remember, classes are functions at runtime: typeof User === 'function'.