JavaScript Programming Paradigms

1️⃣ What is Procedural Programming?

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.

2️⃣ What is Functional Programming?

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.

3️⃣ Object-Oriented Programming (OOP)

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.

4️⃣ Pillars of OOP

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:


// 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).

5️⃣ Constructor Function

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:


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.


Lecture 2: Advanced OOP Concepts

Polymorphism Example

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.

What is 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:


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.

What is 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:


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.

Class in JavaScript

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 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'.