DEV Community

Cover image for Web Dev Day 7: JavaScript Guide Part 2
Bhupesh Kumar
Bhupesh Kumar

Posted on • Edited on

Web Dev Day 7: JavaScript Guide Part 2

What is the DOM in JavaScript?

The Document Object Model (DOM) is a programming interface that allows JavaScript to interact with, manipulate, and update web pages dynamically.

It represents an HTML document as a tree structure, where each HTML element is a node.

1. Understanding the DOM Structure

Consider this HTML document:

<!DOCTYPE html>
<html>
<head>
    <title>DOM Example</title>
</head>
<body>
    <h1 id="heading">Hello, DOM!</h1>
    <p class="text">This is a paragraph.</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

How the DOM Represents This Page:

Document
 ├── html
 │    ├── head
 │    │    ├── title
 │    ├── body
 │         ├── h1 (id="heading")
 │         ├── p (class="text")
Enter fullscreen mode Exit fullscreen mode

2. Accessing the DOM Using JavaScript

Selecting Elements by ID (getElementById)

let heading = document.getElementById("heading");
console.log(heading.textContent);  
// Output: "Hello, DOM!"
Enter fullscreen mode Exit fullscreen mode

Selecting Elements by Class (getElementsByClassName

let paragraphs = document.getElementsByClassName("text");
console.log(paragraphs[0].textContent);  
// Output: "This is a paragraph."
Enter fullscreen mode Exit fullscreen mode

Selecting Elements by Tag Name (getElementsByTagName)

let allHeadings = document.getElementsByTagName("h1");
console.log(allHeadings[0].textContent);  
// Output: "Hello, DOM!"
Enter fullscreen mode Exit fullscreen mode

Modern Way: Using querySelector and querySelectorAll

let heading = document.querySelector("#heading"); // Selects by ID
let paragraph = document.querySelector(".text"); // Selects first element with class
let allParagraphs = document.querySelectorAll(".text"); // Selects all elements with class

console.log(heading.textContent);  
// Output: "Hello, DOM!"
Enter fullscreen mode Exit fullscreen mode

3. Modifying the DOM (Changing Content)

Changing Inner HTML

document.getElementById("heading").innerHTML = "<span style='color:red'>Hello, JS!</span>";
Enter fullscreen mode Exit fullscreen mode

Changing Text Content

document.getElementById("heading").textContent = "Hello, JavaScript!";
Enter fullscreen mode Exit fullscreen mode

4. Manipulating DOM Elements

Adding a New Element (createElement & appendChild)

let newPara = document.createElement("p");
newPara.textContent = "This is a new paragraph!";
document.body.appendChild(newPara);
Enter fullscreen mode Exit fullscreen mode

Removing an Element (removeChild)

let element = document.getElementById("heading");
element.parentNode.removeChild(element);
Enter fullscreen mode Exit fullscreen mode

Changing CSS Styles Using JavaScript

document.getElementById("heading").style.color = "blue";
Enter fullscreen mode Exit fullscreen mode

5. Handling Events in the DOM

Adding an Event Listener

document.getElementById("heading").addEventListener("click", function() {
    alert("Heading clicked!");
});
Enter fullscreen mode Exit fullscreen mode

Removing an Event Listener

function greet() {
    console.log("Heading clicked!");
}

let heading = document.getElementById("heading");
heading.addEventListener("click", greet);
heading.removeEventListener("click", greet);
Enter fullscreen mode Exit fullscreen mode

Manipulating Attributes in JavaScript (DOM)

JavaScript provides methods to add, modify, and remove attributes of HTML elements dynamically.

1. Accessing Attributes

getAttribute()

Gets the value of an attribute.

let link = document.querySelector("a");
console.log(link.getAttribute("href"));  
// Output: The URL inside the `href` attribute
Enter fullscreen mode Exit fullscreen mode

setAttribute()

Sets or updates an attribute.

let link = document.querySelector("a");
link.setAttribute("href", "https://example.com");
console.log(link.getAttribute("href"));  
// Output: "https://example.com"
Enter fullscreen mode Exit fullscreen mode

hasAttribute()

Checks if an element has a specific attribute.

let button = document.querySelector("button");

if (button.hasAttribute("disabled")) {
    console.log("Button is disabled");
} else {
    console.log("Button is enabled");
}
Enter fullscreen mode Exit fullscreen mode

removeAttribute()

Removes an attribute from an element.

let input = document.querySelector("input");
input.removeAttribute("disabled");
Enter fullscreen mode Exit fullscreen mode

2. Working with class Attributes

classList.add()

Adds a class to an element.

let box = document.querySelector(".box");
box.classList.add("active");
Enter fullscreen mode Exit fullscreen mode

classList.remove()

Removes a class.

box.classList.remove("active");
Enter fullscreen mode Exit fullscreen mode

classList.toggle()

Toggles a class on/off.

box.classList.toggle("hidden");

Enter fullscreen mode Exit fullscreen mode

classList.contains()

Checks if an element has a class.

console.log(box.classList.contains("hidden"));  
// Output: true or false
Enter fullscreen mode Exit fullscreen mode

3. Working with data-* Attributes

Custom attributes (data-*) store additional data in elements.

Getting data-* Attributes

let button = document.querySelector("button");
console.log(button.getAttribute("data-user-id"));  
// Output: User ID stored in `data-user-id`
Enter fullscreen mode Exit fullscreen mode

Using dataset for Easier Access

console.log(button.dataset.userId);  
// Output: User ID stored in `data-user-id`
Enter fullscreen mode Exit fullscreen mode

Setting data-* Attributes

button.dataset.status = "active";
console.log(button.dataset.status);  
// Output: "active"
Enter fullscreen mode Exit fullscreen mode

4. Enabling/Disabling Elements (disabled Attribute)

let button = document.querySelector("button");

// Disable the button
button.setAttribute("disabled", true);

// Enable the button
button.removeAttribute("disabled");
Enter fullscreen mode Exit fullscreen mode

Manipulating Styles in JavaScript (DOM)

JavaScript allows you to dynamically change CSS styles on HTML elements using the style property or CSS classes.

1. Changing Inline Styles

You can modify CSS properties using the .style property.

let box = document.querySelector(".box");
box.style.backgroundColor = "blue";
box.style.color = "white";
box.style.padding = "20px";
Enter fullscreen mode Exit fullscreen mode

2. Modifying Multiple Styles Using cssText

box.style.cssText = "background: red; color: white; padding: 15px;";

Enter fullscreen mode Exit fullscreen mode

3. Using classList for CSS Manipulation

Instead of modifying styles directly, use CSS classes for better control.

Adding a Class

box.classList.add("highlight");
Enter fullscreen mode Exit fullscreen mode

Removing a Class

box.classList.remove("highlight");

Enter fullscreen mode Exit fullscreen mode

Toggling a Class (On/Off)

box.classList.toggle("hidden");

Enter fullscreen mode Exit fullscreen mode

Checking if an Element Has a Class

console.log(box.classList.contains("hidden"));  
// Output: true or false
Enter fullscreen mode Exit fullscreen mode

Navigating the Page Using JavaScript (DOM Navigation)

JavaScript provides various DOM navigation methods to move between elements on a web page.

Accessing Parent, Child, and Sibling Elements

Getting the Parent Element (parentNode & parentElement)

let child = document.querySelector(".child");
console.log(child.parentNode);   
console.log(child.parentElement);
Enter fullscreen mode Exit fullscreen mode
Feature                 Method
Get Parent Element  parentNode, parentElement
Get Child Elements  firstElementChild, lastElementChild
Get Sibling Elements    nextElementSibling, previousElementSibling
Scroll to Section   scrollIntoView()
Redirect to URL         window.location.href
Reload Page         window.location.reload()
Navigate History    window.history.back() / forward()
Enter fullscreen mode Exit fullscreen mode

Adding Elements to a Page Using JavaScript (DOM Manipulation)

JavaScript allows you to dynamically create and add elements to the webpage using the DOM API.

1. Creating and Appending an Element

createElement() + appendChild()

let newPara = document.createElement("p"); // Create <p> element
newPara.textContent = "This is a new paragraph!"; // Add text

document.body.appendChild(newPara); // Append to body
Enter fullscreen mode Exit fullscreen mode

2. Adding an Element Inside a Specific Parent

let parentDiv = document.getElementById("container");

let newDiv = document.createElement("div");
newDiv.textContent = "Hello, this is a new div!";
newDiv.classList.add("new-box");

parentDiv.appendChild(newDiv);
Enter fullscreen mode Exit fullscreen mode

3. Using insertBefore() (Insert at a Specific Position)

let list = document.getElementById("list");
let newItem = document.createElement("li");
newItem.textContent = "New Item";

let firstItem = list.firstElementChild; // Get first item
list.insertBefore(newItem, firstItem);  // Insert before it
Enter fullscreen mode Exit fullscreen mode
Feature                        Method
Create an Element          createElement("tag")
Add Text                   element.textContent = "Text"
Append to End                  appendChild(element)
Insert Before                  insertBefore(newElement, referenceElement)
Insert at Specific Position    insertAdjacentHTML(position, html)
Prepend Element                prepend(element)
Clone Element                  cloneNode(true)
Enter fullscreen mode Exit fullscreen mode

Removing Elements from a Page Using JavaScript (DOM Manipulation)

JavaScript allows you to remove elements dynamically from the DOM using various methods.

Removing an Element Using remove()

let element = document.getElementById("box");
element.remove();
Enter fullscreen mode Exit fullscreen mode

2. Removing a Child Element Using removeChild()

let parent = document.getElementById("container");
let child = document.getElementById("child");

parent.removeChild(child);
Enter fullscreen mode Exit fullscreen mode
Feature                       Method
Remove an element         element.remove()
Remove a child                parent.removeChild(child)
Remove first/last child       firstElementChild.remove() / lastElementChild.remove()
Remove all children       innerHTML = ""
Remove using parent       parentNode.removeChild(element)
Remove multiple elements      querySelectorAll().forEach(el => el.remove())
Enter fullscreen mode Exit fullscreen mode

DOM Events in JavaScript

DOM Events allow JavaScript to detect and respond to user interactions such as clicks, key presses, and mouse movements.

1. Adding an Event Listener (addEventListener)

let button = document.getElementById("myButton");

button.addEventListener("click", function() {
    console.log("Button clicked!");
});
Enter fullscreen mode Exit fullscreen mode

onclick and onmouseenter Events in JavaScript

JavaScript provides event handlers like onclick and onmouseenter to detect user interactions such as clicks and mouse movements.

1. onclick Event (Detects Clicks)

The onclick event fires when an element is clicked.

Using onclick with HTML (Inline)

<button onclick="alert('Button clicked!')">Click Me</button>
Enter fullscreen mode Exit fullscreen mode

Using onclick in JavaScript (Better Approach)

let button = document.getElementById("myButton");

button.onclick = function() {
    alert("Button clicked!");
};
Enter fullscreen mode Exit fullscreen mode

Using addEventListener("click") (Best Practice)

let btn = document.getElementById("myButton");

btn.addEventListener("click", () => {
    alert("Button clicked using addEventListener!");
});
Enter fullscreen mode Exit fullscreen mode

2. onmouseenter Event (Mouse Hover)

The onmouseenter event fires when the mouse enters an element.

Example: Changing Background Color on Hover

let box = document.getElementById("box");

box.onmouseenter = function() {
    box.style.backgroundColor = "yellow";
};

box.onmouseleave = function() {
    box.style.backgroundColor = "white";
};
Enter fullscreen mode Exit fullscreen mode

addEventListener() in JavaScript

The addEventListener() method allows JavaScript to attach event listeners to HTML elements dynamically.

It is the preferred method for handling events because it supports multiple handlers.

Basic Syntax

element.addEventListener("event", function);
Enter fullscreen mode Exit fullscreen mode

Event Listeners for Elements in JavaScript

JavaScript event listeners allow you to detect user interactions on elements like buttons, links, inputs, and forms.

1. Adding an Event Listener (addEventListener())

element.addEventListener("event", function);
Enter fullscreen mode Exit fullscreen mode

this in Event Listeners in JavaScript

The this keyword behaves differently in event listeners based on how the function is defined.

1. this in a Regular Function (Refers to the Element)

When using a regular function, this refers to the element that triggered the event.

let button = document.getElementById("myButton");

button.addEventListener("click", function() {
    console.log(this);  // Logs the button element
    this.style.backgroundColor = "blue"; // Changes button color
});
Enter fullscreen mode Exit fullscreen mode

Keyboard Events in JavaScript

JavaScript keyboard events allow you to detect when a user presses or releases a key.

1. Types of Keyboard Events

Event Description
keydown Fires when a key is pressed down
keyup Fires when a key is released
keypress (Deprecated) Similar to keydown, but does not detect Shift, Ctrl, Alt, etc.

Best Practice: Use keydown and keyup instead of keypress.

2. Detecting Key Press (keydown)

document.addEventListener("keydown", (event) => {
    console.log(`Key pressed: ${event.key}`);
});
Enter fullscreen mode Exit fullscreen mode

Form Events in JavaScript

JavaScript form events allow you to detect user interactions with form elements, such as input fields, checkboxes, and buttons.

1. Common Form Events

| Event | Description |
|-------|------------|
| `submit` | Fires when a form is submitted |
| `focus` | Fires when an input field gains focus |
| `blur` | Fires when an input field loses focus |
| `change` | Fires when an input value changes (for dropdowns, checkboxes, etc.) |
| `input` | Fires when the user types in an input field |
| `reset` | Fires when the form is reset |
Enter fullscreen mode Exit fullscreen mode

2. Prevent Default Form Submission (submit Event)

let form = document.getElementById("myForm");

form.addEventListener("submit", (event) => {
    event.preventDefault(); // Prevent page reload
    console.log("Form submitted!");
});
Enter fullscreen mode Exit fullscreen mode

Extracting Form Data in JavaScript

JavaScript allows you to retrieve form input values dynamically for validation, processing, or sending data to a server.

1. Extracting Data Using querySelector

document.getElementById("myForm").addEventListener("submit", function(event) {
    event.preventDefault(); // Prevent page reload

    let name = document.querySelector("#name").value;
    let email = document.querySelector("#email").value;
    let message = document.querySelector("#message").value;

    console.log(`Name: ${name}, Email: ${email}, Message: ${message}`);
});
Enter fullscreen mode Exit fullscreen mode

2. Extracting Data Using elements[]

document.getElementById("myForm").addEventListener("submit", function(event) {
    event.preventDefault();

    let form = event.target;
    let name = form.elements["name"].value;
    let email = form.elements["email"].value;

    console.log(`Name: ${name}, Email: ${email}`);
});
Enter fullscreen mode Exit fullscreen mode

3. Extracting Checkbox and Radio Button Values

document.getElementById("myForm").addEventListener("submit", function(event) {
    event.preventDefault();

    let agree = document.querySelector("#agree").checked;
    let gender = document.querySelector('input[name="gender"]:checked').value;

    console.log(`Agreement: ${agree}, Gender: ${gender}`);
});
Enter fullscreen mode Exit fullscreen mode
Feature                    Method
Get Input Value            document.querySelector("#id").value
Get Checkbox Value     document.querySelector("#id").checked
Get Selected Radio Value document.querySelector('input[name="name"]:checked').value
Get Dropdown Value     document.querySelector("#id").value
Extract All Form Data      new FormData(form).entries()
Send Data to Server    fetch("URL", { method: "POST", body: formData })
Enter fullscreen mode Exit fullscreen mode

change Event in JavaScript

The change event fires when a form input loses focus after a value change.

It is commonly used for dropdowns, checkboxes, radio buttons, and text inputs.

1. Basic Syntax

element.addEventListener("change", function(event) {
    console.log(event.target.value);
});
Enter fullscreen mode Exit fullscreen mode

input Event in JavaScript

The input event fires whenever the value of an input field changes, making it ideal for live updates.

1. Basic Syntax

element.addEventListener("input", function(event) {
    console.log(event.target.value);
});
Enter fullscreen mode Exit fullscreen mode

Event Bubbling in JavaScript

Event bubbling is a concept in the DOM where an event starts from the target element and propagates upwards to its ancestors.

1. How Event Bubbling Works

Consider the following HTML:

<div id="parent">
    <button id="child">Click Me</button>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, let's add event listeners:

document.getElementById("child").addEventListener("click", () => {
    console.log("Child clicked!");
});

document.getElementById("parent").addEventListener("click", () => {
    console.log("Parent clicked!");
});
Enter fullscreen mode Exit fullscreen mode

Clicking the button logs:

Child clicked!
Parent clicked!

The event starts at the child (button) and bubbles up to the parent (div).

2. Stopping Event Bubbling (stopPropagation())

Use event.stopPropagation() to prevent bubbling:

document.getElementById("child").addEventListener("click", (event) => {
    event.stopPropagation();
    console.log("Child clicked!");
});

document.getElementById("parent").addEventListener("click", () => {
    console.log("Parent clicked!");
});
Enter fullscreen mode Exit fullscreen mode

Now, clicking the button only logs:

Child clicked!

The parent event is NOT triggered.

Event Delegation in JavaScript

Event Delegation is a technique in JavaScript where a single event listener is added to a parent element to handle events on multiple child elements, even if they are added dynamically.

1. Why Use Event Delegation?

🔹 Without Event Delegation (Adding Event Listeners to Each Button)

let buttons = document.querySelectorAll(".btn");

buttons.forEach(button => {
    button.addEventListener("click", () => {
        console.log("Button clicked!");
    });
});
Enter fullscreen mode Exit fullscreen mode

Does not work for dynamically added elements.

2. Using Event Delegation

document.getElementById("parent").addEventListener("click", (event) => {
    if (event.target.matches(".btn")) {
        console.log(`Button Clicked: ${event.target.textContent}`);
    }
});
Enter fullscreen mode Exit fullscreen mode

Why Use?

  • Only one event listener is needed.
  • Works for both existing and dynamically added elements.

JavaScript Call Stack

The Call Stack in JavaScript is a mechanism that the JavaScript engine uses to keep track of function calls.

It follows the Last In, First Out (LIFO) principle.


1. What is the Call Stack?

  • When you invoke a function, JavaScript adds it (pushes) onto the stack.
  • When the function returns, JavaScript removes it (pops) from the stack.
  • The most recent function call is always at the top of the stack.

2. How It Works

Example:

function greet() {
    console.log("Hello");
}

function welcome() {
    greet();
    console.log("Welcome!");
}

welcome();
Enter fullscreen mode Exit fullscreen mode

Visualizing the JavaScript Call Stack

1. Basic Example

function greet() {
    console.log("Hello!");
}

function welcome() {
    greet();
    console.log("Welcome!");
}

welcome();

Enter fullscreen mode Exit fullscreen mode

Call Stack Step-by-Step:

  1. Initially:
(empty)
Enter fullscreen mode Exit fullscreen mode
  1. Call welcome()
| welcome |
Enter fullscreen mode Exit fullscreen mode
  1. Inside welcome(), call greet()
| greet |
| welcome |
Enter fullscreen mode Exit fullscreen mode
  1. greet() logs "Hello" and finishes
| welcome |
Enter fullscreen mode Exit fullscreen mode
  1. welcome() logs "Welcome!" and finishes
(empty)
Enter fullscreen mode Exit fullscreen mode

Final Output in Console:

Hello!
Welcome!
Enter fullscreen mode Exit fullscreen mode

2. Nested Function Calls Example

function first() {
    console.log("First");
    second();
}

function second() {
    console.log("Second");
    third();
}

function third() {
    console.log("Third");
}

first();
Enter fullscreen mode Exit fullscreen mode

Call Stack Timeline:

Moment Call Stack
Start (empty)
Call first() first()
Inside first(), call second() second()first()
Inside second(), call third() third()second()first()
third() completes second()first()
second() completes first()
first() completes (empty)

Final Output in Console:

First
Second
Third
Enter fullscreen mode Exit fullscreen mode

3. Visual Representation (Graphical)

Time ➡️
----------------------------------------------------

Step 1: Call first()

[ first ]

Step 2: first() calls second()

[ second ]
[ first ]

Step 3: second() calls third()

[ third ]
[ second ]
[ first ]

Step 4: third() finishes

[ second ]
[ first ]

Step 5: second() finishes

[ first ]

Step 6: first() finishes

(empty)
Enter fullscreen mode Exit fullscreen mode

Breakpoints in JavaScript (Debugging with DevTools)

Breakpoints are a powerful feature that allows you to pause code execution at a specific line, so you can inspect values, control flow, and debug issues step-by-step.


JavaScript is Single-Threaded

JavaScript is a single-threaded programming language, meaning it can only execute one task at a time in a single line of execution.

1. What Does Single-Threaded Mean?

  • Only one command is being processed at a time.
  • One call stack and one memory heap are used.
  • No two pieces of code run simultaneously in the same thread.

Analogy:

Imagine a cashier at a store who can only serve one customer at a time.

The next customer must wait until the current one is fully processed.


2. How JavaScript Executes Code

Step Description
1 Code enters the Call Stack one function at a time.
2 Each function completes before the next one is run.
3 If a function is waiting (e.g., timer, fetch API), it is offloaded to the Web APIs and comes back later via the Event Loop.

JavaScript is fast not because it is multi-threaded, but because it handles asynchronous tasks smartly using the Event Loop.


Example with Asynchronous Behavior (Still Single-Threaded)

console.log("Start");

setTimeout(() => {
    console.log("Timeout callback");
}, 2000);

console.log("End");
Enter fullscreen mode Exit fullscreen mode

Callback Hell in JavaScript

Callback Hell refers to a situation in JavaScript where multiple nested callbacks make code difficult to read, understand, and maintain.


1. What is a Callback?

A callback is a function passed as an argument to another function, and it is executed after some operation completes.

Example:

function fetchData(callback) {
    setTimeout(() => {
        console.log("Data fetched");
        callback();
    }, 1000);
}

fetchData(() => {
    console.log("Callback executed");
});
Enter fullscreen mode Exit fullscreen mode

2. What is Callback Hell?

When callbacks are nested inside other callbacks, it leads to deeply indented, hard-to-maintain code:

Example:

setTimeout(() => {
    console.log("Step 1");
    setTimeout(() => {
        console.log("Step 2");
        setTimeout(() => {
            console.log("Step 3");
            setTimeout(() => {
                console.log("Step 4");
            }, 1000);
        }, 1000);
    }, 1000);
}, 1000);
Enter fullscreen mode Exit fullscreen mode

Step 1
Step 2
Step 3
Step 4


Promises in JavaScript

A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.


1. Why Promises?

Before Promises, callbacks were used to handle asynchronous code, which led to callback hell.

Promises solve this by offering a cleaner, chainable syntax.


2. States of a Promise

A Promise can be in one of three states:

State Description
Pending Initial state, neither fulfilled nor rejected
Fulfilled Operation completed successfully
Rejected Operation failed

3. Creating a Promise

const myPromise = new Promise((resolve, reject) => {
    let success = true;

    if (success) {
        resolve("Data loaded!");
    } else {
        reject("Error loading data.");
    }
});
Enter fullscreen mode Exit fullscreen mode

.then() and .catch() in JavaScript Promises

JavaScript Promises come with .then() and .catch() methods to handle asynchronous operations successfully or with errors.


.then() – Handling Success

The .then() method is used to specify what to do when the Promise is fulfilled.

Syntax:

promise.then(onFulfilled);
Enter fullscreen mode Exit fullscreen mode
let successPromise = new Promise((resolve, reject) => {
    resolve("Task Successful!");
});

successPromise.then(result => {
    console.log(result); // Output: Task Successful!
});
Enter fullscreen mode Exit fullscreen mode

.catch() – Handling Errors

The .catch() method is used to handle rejections (errors) in Promises.

Syntax:

promise.catch(onRejected);
Enter fullscreen mode Exit fullscreen mode

Example:

let failurePromise = new Promise((resolve, reject) => {
    reject("❌ Task Failed!");
});

failurePromise
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.log(error); // Output: ❌ Task Failed!
    });
Enter fullscreen mode Exit fullscreen mode

Chaining .then() and .catch()

You can chain multiple .then() calls. If any error occurs, it will be caught in .catch().

Example:

new Promise((resolve, reject) => {
    resolve(10);
})
.then(num => {
    return num * 2;
})
.then(result => {
    console.log("Result:", result); // Output: Result: 20
})
.catch(err => {
    console.error("Error:", err);
});
Enter fullscreen mode Exit fullscreen mode

Promise Chaining in JavaScript

Promise chaining allows you to run multiple asynchronous operations in sequence, where the output of one .then() becomes the input of the next.


1. What is Promise Chaining?

You can return a value or another Promise from .then() and chain further .then() calls:

fetchData()
  .then(processData)
  .then(displayData)
  .catch(handleError);
Enter fullscreen mode Exit fullscreen mode

2. Basic Example:

new Promise((resolve, reject) => {
    resolve(2);
})
.then(num => {
    console.log("Step 1:", num); // Step 1: 2
    return num * 2;
})
.then(num => {
    console.log("Step 2:", num); // Step 2: 4
    return num * 3;
})
.then(num => {
    console.log("Step 3:", num); // Step 3: 12
});
Enter fullscreen mode Exit fullscreen mode

3. Returning a New Promise in the Chain

function delayedStep(value, delay) {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log("Step:", value);
            resolve(value);
        }, delay);
    });
}

delayedStep(1, 1000)
  .then(() => delayedStep(2, 1000))
  .then(() => delayedStep(3, 1000))
  .then(() => console.log("All steps done!"));
Enter fullscreen mode Exit fullscreen mode

Step: 1
Step: 2
Step: 3
All steps done!

Results and Errors in JavaScript Promises

JavaScript Promises allow you to handle successful results and errors in asynchronous operations in a clean, chainable way.


Handling Results with .then()

The .then() method is used to receive the result when a Promise is fulfilled.

Example:

let promise = new Promise((resolve, reject) => {
    resolve("Data loaded successfully!");
});

promise.then(result => {
    console.log("✅ Result:", result);
});
Enter fullscreen mode Exit fullscreen mode

Handling Errors with .catch()

The .catch() method is used to catch errors when a Promise is rejected or if an error is thrown in a .then() chain.

Example:

let errorPromise = new Promise((resolve, reject) => {
    reject("Server error occurred.");
});

errorPromise
  .then(result => {
      console.log("This will not run.");
  })
  .catch(error => {
      console.log("❌ Error:", error);
  });
Enter fullscreen mode Exit fullscreen mode

Returning Values from .then()

Each .then() passes its return value to the next .then() in the chain:

Promise.resolve(5)
  .then(num => num * 2)
  .then(result => {
      console.log("✅ Final Result:", result); // 10
  });
Enter fullscreen mode Exit fullscreen mode

async Functions in JavaScript

async functions make writing asynchronous code in JavaScript simpler and more readable, by allowing the use of await to pause execution until a Promise is resolved or rejected.


1. What is an async Function?

  • An async function always returns a Promise.
  • Inside an async function, you can use the await keyword to wait for a Promise to resolve.

Basic Syntax:

async function myFunction() {
    // code
}
Enter fullscreen mode Exit fullscreen mode

2. Example: Returning a Promise Automatically

async function greet() {
    return "Hello!";
}

greet().then(result => {
    console.log(result); // Output: Hello!
});
Enter fullscreen mode Exit fullscreen mode

The return value is automatically wrapped in a Promise.

await Keyword in JavaScript

The await keyword is used inside async functions to pause the execution until a Promise is resolved or rejected.


1. What Does await Do?

  • Waits for the result of a Promise.
  • Pauses execution of the surrounding async function.
  • Resumes when the Promise is resolved (or throws an error if rejected).

2. Basic Syntax

let result = await promise;
Enter fullscreen mode Exit fullscreen mode

await can only be used inside an async function (or top-level in modules).

3. Example with Delay

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function run() {
    console.log("⏱️ Waiting...");
    await delay(2000);
    console.log("✅ Done after 2 seconds");
}

run();
Enter fullscreen mode Exit fullscreen mode

await delay(2000) pauses for 2 seconds before continuing.

4. Awaiting a Fetch Call

async function getUser() {
    const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
    const user = await response.json();
    console.log("👤 User:", user);
}
Enter fullscreen mode Exit fullscreen mode

getUser();
📌 await makes asynchronous HTTP calls look like synchronous code.

Handling Rejections with await in JavaScript

When using await with Promises in async functions, you must handle rejections to prevent your app from crashing or behaving unexpectedly.


Why Handle Rejections?

  • If a Promise is rejected, await will throw an error.
  • Without handling, it may cause uncaught exceptions.

1. Using try...catch with await

The most common and reliable way to handle rejections is with a try...catch block.

Example:

async function fetchData() {
    try {
        const response = await fetch("https://invalid.api.url");
        const data = await response.json();
        console.log("✅ Data:", data);
    } catch (error) {
        console.error("❌ Error fetching data:", error.message);
    }
}

fetchData();
Enter fullscreen mode Exit fullscreen mode

Why Use?

Gracefully catches any errors (like network failures, API issues, etc.).

2. Custom Rejection Handling

You can manually reject Promises and catch them:

function getUser(id) {
    return new Promise((resolve, reject) => {
        if (id > 0) {
            resolve({ id, name: "Alice" });
        } else {
            reject("Invalid user ID");
        }
    });
}

async function loadUser() {
    try {
        const user = await getUser(-1);
        console.log("User:", user);
    } catch (err) {
        console.error("❌ Rejection:", err);
    }
}

loadUser();
Enter fullscreen mode Exit fullscreen mode

3. Optional: Handle with .catch() after await

You can also use .catch() inline with await, though it's less common than try...catch.

const response = await fetch("/api/data").catch(err => {
    console.error("❌ Fetch error:", err.message);
});
Enter fullscreen mode Exit fullscreen mode

📌 Note: Further code will still execute even if this fails — be cautious.

What is an API?

API stands for Application Programming Interface.

An API is a set of rules that allows one software application to communicate with another. It defines how requests and responses should be formatted, much like a contract between two programs.


1. Simple Definition

An API is like a waiter in a restaurant who takes your order (request), tells the kitchen (server), and brings back your food (response).


2. Real-World Analogy

You use an API every day:

  • Weather app fetches weather → it calls a weather API.
  • Instagram posts are loaded → it uses Instagram’s API.
  • Google Maps in your food app? → powered by the Maps API.

3. Types of APIs

Type Description
Web API Communication over the internet (HTTP/S)
Browser API Built into the browser (e.g., DOM, fetch())
Library API Functions exposed by a library (e.g., jQuery)
Operating System API Interfaces for OS features (e.g., file system)

4. Web API Example (Using Fetch)

fetch("https://api.example.com/data")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("❌ Error:", error));
Enter fullscreen mode Exit fullscreen mode

5. How Does an API Work?

Client (Frontend) ➡️ Sends Request ➡️
           Server (API) ➡️ Processes & Sends Response ➡️
                          Client uses the result
Enter fullscreen mode Exit fullscreen mode

6. Common Data Format: JSON

Most modern APIs communicate using JSON (JavaScript Object Notation).

Example API Response:

{
  "name": "Alice",
  "age": 30,
  "location": "Canada"
}
Enter fullscreen mode Exit fullscreen mode

7. HTTP Methods Used in APIs

Method  Purpose
GET Read data
POST    Create data
PUT Update data
DELETE  Remove data
Enter fullscreen mode Exit fullscreen mode

What is JSON?

JSON stands for JavaScript Object Notation.

It is a lightweight data format used for storing and exchanging data between servers and clients in a human-readable format.


1. Simple Definition

JSON is a text format for representing structured data (like objects and arrays) in a way that's easy to read and easy for machines to parse.


2. JSON Syntax Basics

  • Data is in key-value pairs
  • Data is separated by commas
  • Curly braces {} hold objects
  • Square brackets [] hold arrays
  • Keys and string values must be in double quotes

Example JSON:

{
  "name": "Alice",
  "age": 25,
  "isStudent": false,
  "skills": ["JavaScript", "Python"],
  "address": {
    "city": "Toronto",
    "country": "Canada"
  }
}
Enter fullscreen mode Exit fullscreen mode

3. JSON vs JavaScript Object

Feature JSON    JavaScript Object
Quotes on keys  Required ("key")    Optional (key or "key")
Comments    ❌ Not allowed ✅ Allowed
Methods ❌ Not supported   ✅ Can include functions
Enter fullscreen mode Exit fullscreen mode

4. JSON in APIs

APIs typically send and receive data in JSON format.

Example with Fetch:

fetch("https://api.example.com/user")
  .then(response => response.json())
  .then(data => {
    console.log(data.name); // Accessing JSON property
  });
Enter fullscreen mode Exit fullscreen mode

6. Real-World Use Cases

  • API responses
  • Config files
  • Storing data in localStorage
  • Data exchange in mobile/web apps

Accessing JSON Data in JavaScript

JSON (JavaScript Object Notation) is a format used to exchange data. Once parsed into a JavaScript object, you can access its data using dot notation or bracket notation.


1. Parsing JSON to JavaScript

Before you access data, you must parse the JSON string into a JavaScript object:

let jsonString = '{"name": "Alice", "age": 25, "skills": ["JS", "Python"]}';

let user = JSON.parse(jsonString);
Enter fullscreen mode Exit fullscreen mode

2. Accessing JSON Object Properties

Dot Notation (most common):

console.log(user.name);  // "Alice"
console.log(user.age);   // 25
Enter fullscreen mode Exit fullscreen mode

Bracket Notation (useful for dynamic keys or invalid identifiers):

console.log(user["skills"]);        // ["JS", "Python"]
console.log(user["name"]);          // "Alice"

let key = "age";
console.log(user[key]);             // 25
Enter fullscreen mode Exit fullscreen mode

3. Accessing Nested JSON Data

{
  "name": "Bob",
  "address": {
    "city": "Toronto",
    "postal": "M4B1B3"
  }
}
Enter fullscreen mode Exit fullscreen mode

JavaScript Example:

let data = JSON.parse('{"name":"Bob","address":{"city":"Toronto","postal":"M4B1B3"}}');

console.log(data.address.city);     // "Toronto"
console.log(data["address"]["postal"]); // "M4B1B3"
Enter fullscreen mode Exit fullscreen mode

4. Accessing JSON Arrays

{
  "users": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ]
}
Enter fullscreen mode Exit fullscreen mode

JavaScript Example:

let data = JSON.parse('{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}');

console.log(data.users[0].name);   // "Alice"
console.log(data.users[1]["id"]);  // 2
Enter fullscreen mode Exit fullscreen mode

5. Looping Through JSON Data

Using forEach:

data.users.forEach(user => {
    console.log(user.name);  // "Alice", "Bob"
});
Enter fullscreen mode Exit fullscreen mode

Using for...of:

for (let user of data.users) {
    console.log(user.id);   // 1, 2
}
Enter fullscreen mode Exit fullscreen mode

6. Accessing Before Parsing = ❌ Error

let jsonData = '{"name": "John"}';

console.log(jsonData.name); // ❌ undefined
Enter fullscreen mode Exit fullscreen mode

✅ Correct:

let parsed = JSON.parse(jsonData);
console.log(parsed.name);   // ✅ "John"
Enter fullscreen mode Exit fullscreen mode

Top API Testing Tools for Developers

API testing is essential for verifying that your backend services are working correctly, securely, and efficiently.

These tools help send requests, inspect responses, automate tests, and document APIs.


1. Postman

Postman Logo

Postman is the most popular API testing tool with a user-friendly UI.

Features:

  • Create and send HTTP requests (GET, POST, PUT, DELETE)
  • Organize requests in collections and folders
  • Add environments and variables
  • Automate tests with JavaScript
  • View detailed request/response logs

Best For:

  • Manual and automated API testing
  • Collaborating with teams

🔗 https://www.postman.com


2. Insomnia

Insomnia is a sleek, fast alternative to Postman with a focus on simplicity.

Features:

  • Support for REST, GraphQL, gRPC
  • Environment variables
  • JSON schema validation
  • Plugin support and dark mode

Best For:

  • Developers who prefer a minimal, keyboard-friendly tool

🔗 https://insomnia.rest


3. Swagger (OpenAPI)

Swagger UI and SwaggerHub help you document and test REST APIs.

Features:

  • Live API documentation
  • Send requests from the UI
  • Auto-generate client SDKs
  • API mocking

Best For:

  • Testing APIs from OpenAPI specs
  • API-first development

🔗 https://swagger.io/tools/swagger-ui/


4. Hoppscotch (formerly Postwoman)

Hoppscotch is a fast, open-source, browser-based API client.

Features:

  • Lightweight and blazing fast
  • Send requests for REST, GraphQL, WebSocket
  • Open source and privacy-focused

Best For:

  • Quick in-browser testing without installation

🔗 https://hoppscotch.io


5. REST Assured (Java)

REST Assured is a Java library for automating API tests.

Features:

  • Fluent syntax for writing tests
  • Integrates with JUnit/TestNG
  • Validates responses, headers, status codes

Best For:

  • Backend developers using Java

🔗 https://rest-assured.io


6. cURL (Command-Line)

cURL is a command-line tool to send HTTP requests from the terminal.

Features:

  • Lightweight, no UI
  • Works on Linux, Mac, Windows
  • Perfect for scripting and automation

Example:

curl -X POST https://api.example.com/data -H "Content-Type: application/json" -d '{"name":"Alice"}'
Enter fullscreen mode Exit fullscreen mode

7. JMeter

Apache JMeter is great for performance and load testing APIs.

Features:

  • Simulate heavy traffic on APIs
  • Record and replay requests
  • Built-in reports and graphs

What is AJAX?

AJAX stands for Asynchronous JavaScript and XML.

It is a technique that allows web pages to send and receive data from a server asynchronously, without reloading the entire page.


1. Simple Definition

AJAX enables your website to communicate with the server in the background, updating parts of a web page without refreshing the whole page.


2. Real-World Examples of AJAX

  • Submitting a form without reloading the page
  • Auto-search suggestions (like Google search)
  • Live data updates (chat apps, news feeds)
  • Loading content on scroll (infinite scroll)

3. Key Components of AJAX

Component Role
JavaScript Controls the logic
XMLHttpRequest or fetch() Sends requests to the server
JSON/XML/HTML Formats the data being sent/received
DOM Updates the web page without reloading

4. Modern AJAX with fetch()

fetch("https://jsonplaceholder.typicode.com/users/1")
.then(response => response.json())
.then(data => {
console.log("User:", data.name);
})
.catch(error => {
console.error("Error fetching data:", error);
});

No page reload, but user data is fetched and shown!

HTTP Verbs (Methods) Explained

HTTP verbs (also known as HTTP methods) define the type of action to perform when making requests to a server.

They are used in REST APIs to map CRUD operations (Create, Read, Update, Delete).


1. Common HTTP Verbs

Verb Purpose CRUD Equivalent Typical Use
GET Retrieve data Read Fetching user info, posts
POST Create new data Create Submitting forms, creating users
PUT Replace existing data Update Full update of a resource
PATCH Partially update data Update Update specific fields
DELETE Remove data Delete Deleting a user or a record

Adding Information in URLs (Query Parameters & URL Path)

In web development, you often need to send information to the server through the URL.

This can be done using:

  1. Query Parameters
  2. Path Parameters

1. Query Parameters (Key-Value Pairs)

Query parameters are added to the URL after a ?, using & to separate multiple values.

Syntax:

https://example.com/api/users?name=Alice&age=25

JavaScript Example with fetch():

let name = "Alice";
let age = 25;

fetch(`https://example.com/api/users?name=${name}&age=${age}`)
  .then(res => res.json())
  .then(data => console.log(data));
Enter fullscreen mode Exit fullscreen mode

📌 Use when sending optional or filter data

2. Path Parameters (Clean URLs)

Path parameters are embedded directly in the URL path, often used for resource IDs.

Syntax:

https://example.com/api/users/123

JavaScript Example:

let userId = 123;

fetch(`https://example.com/api/users/${userId}`)
  .then(res => res.json())
  .then(data => console.log(data));
Enter fullscreen mode Exit fullscreen mode

📌 Use when accessing specific resources (e.g., user, product, post).

3. When to Use Which?

Use Case    Path Parameter  Query Parameter
Get user by ID  /users/123  ❌
Filter/search users /users?name=John    ✅
Paginate data   /products?page=2    ✅
Fetch related resource  /users/123/posts    ✅ or Path-based
Enter fullscreen mode Exit fullscreen mode

HTTP Headers Explained

HTTP headers are key-value pairs sent between the client and server in every HTTP request and response.

They provide metadata about the request/response and are essential for things like authentication, content type, caching, etc.


1. Types of HTTP Headers

Type Purpose
Request Headers Sent by the client (browser, app) to the server
Response Headers Sent by the server back to the client
General Headers Used by both request and response
Entity Headers Define body content information (length, type, etc.)

2. Common Request Headers

Header Description
Accept Specifies the media types the client can handle
Content-Type Type of data being sent (e.g., application/json)
Authorization Authentication credentials (e.g., Bearer token)
User-Agent Info about the client/browser
Cache-Control Caching behavior

Example of Request Headers in fetch()

fetch("https://api.example.com/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer your_token_here"
  },
  body: JSON.stringify({ name: "Alice" })
});
Enter fullscreen mode Exit fullscreen mode

Your First API Request Using fetch() in JavaScript

The fetch() method is a modern way to make HTTP requests in JavaScript.

It returns a Promise, making it ideal for handling asynchronous API calls like GET, POST, PUT, and DELETE.


1. Basic Syntax

fetch(url, options)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("❌ Error:", error));
Enter fullscreen mode Exit fullscreen mode

Your First API Request Using fetch() with async/await

Using async/await with fetch() provides a cleaner, more readable way to make asynchronous API requests in JavaScript.


1. Basic Syntax

async function fetchData() {
  try {
    const response = await fetch("https://example.com/api");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("❌ Error:", error.message);
  }
}
Enter fullscreen mode Exit fullscreen mode

Axios in JavaScript – HTTP Requests Made Easy

Axios is a popular JavaScript library used to make HTTP requests from the browser or Node.js.

It provides a simple, Promise-based API with powerful features for working with APIs.


✅ 1. Why Use Axios?

Compared to the native fetch() API, Axios offers:

  • 🔁 Automatic JSON data transformation
  • 🌐 Better error handling
  • 📦 Built-in request/response interceptors
  • 🕒 Timeout support
  • 🌍 Supports older browsers (unlike fetch)
  • 🧼 Cleaner syntax

2. Installing Axios

In a browser (CDN):

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

In a Node.js project:

npm install axios

Sending Headers with API Requests in JavaScript

HTTP headers are used to pass additional information between the client and server.

This includes data like content type, authentication tokens, API keys, etc.

You can send headers using both fetch() and Axios.


1. Sending Headers with fetch()

fetch("https://api.example.com/data", {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer your_token_here"
  }
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("❌ Error:", error));
Enter fullscreen mode Exit fullscreen mode

2. Sending Headers with Axios

Axios has a more concise syntax for headers:

axios.get("https://api.example.com/data", {
  headers: {
    "Authorization": "Bearer your_token_here"
  }
});
Enter fullscreen mode Exit fullscreen mode

Activity: Using Query Strings to Filter API Results

In this activity, you’ll learn how to use query strings in API requests to filter data, search records, and pass parameters through the URL.


Objective

Make API requests that use query strings to filter user data based on:

  • Name
  • Limit of records
  • Sort order

1. What is a Query String?

A query string is part of a URL that passes key-value pairs to the server.

It starts with a ? and uses & to separate multiple parameters.

Example:

https://api.example.com/users?name=Alice&limit=5


2. Sample API (You Can Use)

You can test this with the JSONPlaceholder API:

https://jsonplaceholder.typicode.com/users

This API doesn't support query filters, but we’ll simulate how it would work.


3. Activity Instructions

Step 1: Basic GET Request

fetch("https://jsonplaceholder.typicode.com/users")
  .then(res => res.json())
  .then(data => console.log("All users:", data));
Enter fullscreen mode Exit fullscreen mode

Step 2: Filter with a Query String

Let’s simulate filtering by name (e.g., ?name=Leanne):

let name = "Leanne";

fetch(`https://jsonplaceholder.typicode.com/users?name=${encodeURIComponent(name)}`)
  .then(res => res.json())
  .then(data => {
    console.log(`Users matching name '${name}':`, data);
  });
Enter fullscreen mode Exit fullscreen mode

Step 3: Add More Query Parameters

let name = "Leanne";
let sortBy = "username";

fetch(`https://jsonplaceholder.typicode.com/users?name=${name}&sort=${sortBy}`)
  .then(res => res.json())
  .then(data => console.log(data));
Enter fullscreen mode Exit fullscreen mode

📌 Even though JSONPlaceholder won’t apply the filter or sort, the URL structure is valid.

4. Activity Challenge

Write a function that accepts filters and returns the request URL:

function buildQueryURL(baseURL, filters) {
  const query = new URLSearchParams(filters).toString();
  return `${baseURL}?${query}`;
}

const url = buildQueryURL("https://jsonplaceholder.typicode.com/users", {
  name: "Ervin",
  limit: 3,
  sort: "email"
});

console.log("Request URL:", url);
Enter fullscreen mode Exit fullscreen mode

Output:

Request URL: https://jsonplaceholder.typicode.com/users?name=Ervin&limit=3&sort=email
Enter fullscreen mode Exit fullscreen mode

Object-Oriented Programming (OOP) in JavaScript

JavaScript supports OOP principles like Encapsulation, Inheritance, Abstraction, and Polymorphism through objects and classes.


1. Objects

Basic object with properties and methods:

const user = {
  name: "Bhupesh",
  age: 25,
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

user.greet(); // Hello, Bhupesh
Enter fullscreen mode Exit fullscreen mode

2. Constructor Function

Before ES6, constructor functions were used to create multiple instances.

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hi, I'm ${this.name}`);
};

const p1 = new Person("Alice", 30);
p1.greet(); // Hi, I'm Alice
Enter fullscreen mode Exit fullscreen mode

3. ES6 Classes

Modern syntax for creating blueprints:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hi, I'm ${this.name}`);
  }
}

const person1 = new Person("Bob", 28);
person1.greet(); // Hi, I'm Bob
Enter fullscreen mode Exit fullscreen mode

4. Inheritance

One class can extend another:

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

const d = new Dog("Rex");
d.speak(); // Rex barks.
Enter fullscreen mode Exit fullscreen mode

5. Encapsulation

Keep data protected using closures or #privateFields (modern JS):

class BankAccount {
  #balance = 0; // private field

  deposit(amount) {
    this.#balance += amount;
  }

  getBalance() {
    return this.#balance;
  }
}

const acc = new BankAccount();
acc.deposit(100);
console.log(acc.getBalance()); // 100
Enter fullscreen mode Exit fullscreen mode

6. Polymorphism

Methods behave differently based on the object context:

class Shape {
  draw() {
    console.log("Drawing a shape...");
  }
}

class Circle extends Shape {
  draw() {
    console.log("Drawing a circle...");
  }
}

let shape1 = new Shape();
let shape2 = new Circle();

shape1.draw(); // Drawing a shape...
shape2.draw(); // Drawing a circle...
Enter fullscreen mode Exit fullscreen mode

Object Prototypes in JavaScript

JavaScript uses prototypal inheritance, meaning objects can inherit properties and methods from a prototype.


1. What is a Prototype?

Every JavaScript object has a hidden internal property called [[Prototype]], accessible via:

Object.getPrototypeOf(obj)
Enter fullscreen mode Exit fullscreen mode

2. Prototype Chain

When you access a property or method on an object, JS looks up the prototype chain:

const user = {
  name: "Alice"
};

console.log(user.toString()); // inherited from Object.prototype
Enter fullscreen mode Exit fullscreen mode
3. ES6 Classes Use Prototypes Under the Hood
class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, ${this.name}`);
  }
}
Enter fullscreen mode Exit fullscreen mode
const u1 = new User("John");
u1.greet(); // Hello, John
Enter fullscreen mode Exit fullscreen mode
  • Here, greet() is on User.prototype.

Factory Functions in JavaScript

A Factory Function is a function that returns a new object. It allows you to create multiple similar objects without using classes or constructor functions.


1. Basic Syntax

function createUser(name, age) {
  return {
    name,
    age,
    greet() {
      console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
    }
  };
}
Enter fullscreen mode Exit fullscreen mode
const user1 = createUser("Bhupesh", 25);
const user2 = createUser("Alice", 30);

user1.greet(); // Hi, I'm Bhupesh and I'm 25 years old.
user2.greet(); // Hi, I'm Alice and I'm 30 years old.
Enter fullscreen mode Exit fullscreen mode

new Operator in JavaScript

The new operator in JavaScript is used to create instances of objects from constructor functions or classes.


1. How new Works

When you use the new keyword with a constructor function:

function Person(name) {
  this.name = name;
  this.sayHi = function () {
    console.log(`Hi, I'm ${this.name}`);
  };
}

const p1 = new Person("Bhupesh");
p1.sayHi(); // Hi, I'm Bhupesh
Enter fullscreen mode Exit fullscreen mode

2. What new Does Internally

Using new Person("Bhupesh") is like doing the following steps manually:

  • Create a blank object: {}
  • Set its prototype: proto = Person.prototype
  • Bind this to the new object
  • Run the constructor function
  • Return the new object

3. Using new with ES6 Classes

class Car {
  constructor(brand) {
    this.brand = brand;
  }

  drive() {
    console.log(`${this.brand} is driving.`);
  }
}

const car1 = new Car("Tesla");
car1.drive(); // Tesla is driving.
Enter fullscreen mode Exit fullscreen mode

4. Without new — Common Mistake

If you forget new, this becomes undefined or refers to the global object (in non-strict mode):

function Animal(name) {
  this.name = name;
}

const a = Animal("Tiger");
console.log(a); // undefined
Enter fullscreen mode Exit fullscreen mode

Classes in JavaScript

JavaScript introduced the class syntax in ES6 (ECMAScript 2015) as a cleaner, more familiar way to create objects and handle inheritance.

Under the hood, JavaScript classes are syntactic sugar over its prototype-based inheritance model.


1. Basic Class Declaration

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
  }
}

const p1 = new Person("Bhupesh", 25);
p1.greet(); // Hi, I'm Bhupesh and I'm 25 years old.
Enter fullscreen mode Exit fullscreen mode

2. Using super() to Access Parent Class

class Employee {
  constructor(name) {
    this.name = name;
  }
}

class Manager extends Employee {
  constructor(name, department) {
    super(name); // Call parent constructor
    this.department = department;
  }

  info() {
    console.log(`${this.name} manages ${this.department}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Class Fields (Public and Private)

class Counter {
  count = 0; // Public field
  #secret = 42; // Private field (ES2022+)

  increment() {
    this.count++;
  }

  revealSecret() {
    return this.#secret;
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Static Methods

Static methods are called on the class, not instances.

class MathUtils {
  static square(x) {
    return x * x;
  }
}

console.log(MathUtils.square(4)); // 16
Enter fullscreen mode Exit fullscreen mode
Feature Syntax Example
Class declaration class MyClass {}
Constructor constructor(args) { ... }
Method methodName() {}
Inheritance class B extends A
Call parent super()
Static method static myMethod()
Private field #myPrivate = value

JS (OOP) Summary Sheet


Q1. What is Object-Oriented Programming (OOP)?

A:

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of objects and classes. It structures code into reusable blueprints (classes) that can be used to create individual instances (objects).


Q2. What are some benefits of using OOP in JavaScript?

A:

  • 🧱 Improved code organization
  • 🔁 Reusability of code
  • 🔧 Easier code maintenance
  • 🌐 Real-world modeling using objects

Q3. What is the difference between an object and a class in JavaScript?

A:

  • Object: An instance containing properties and methods.
  • Class: A blueprint for creating objects.

Objects are created from classes or constructor functions.


Q4. What is a constructor function in JS?

A:

A constructor function is a special function used to create and initialize objects in JavaScript. When called with the new keyword, it sets up properties and methods for the new object.


Q5. What is a prototype chain in JavaScript?

A:

Every JavaScript object has a prototype, and that prototype is also an object. This forms a prototype chain, which continues until it reaches null.

let obj = {};
console.log(Object.getPrototypeOf(obj)); // => Object.prototype
Enter fullscreen mode Exit fullscreen mode

Q6. What is the difference between a constructor and a class in JS?

A:

  • Constructor Function: A function used to create and initialize an object.
  • Class: A syntactic sugar introduced in ES6 that makes constructor functions easier to work with.

Both serve the same purpose, but class syntax is cleaner and more intuitive.

Q7. Why is the new keyword used in JavaScript?

A:
The new keyword is used to:

  • Create a new object
  • Set the constructor's this to that object
  • Return the newly created object

Q8. What is Inheritance in OOP?

A:
Inheritance allows a class to inherit properties and methods from another class. This promotes reusability and models real-world relationships.

class Animal {
  speak() {
    console.log("Animal speaks");
  }
}

class Dog extends Animal {
  speak() {
    console.log("Dog barks");
  }
}
Enter fullscreen mode Exit fullscreen mode

Q9. What is the super keyword in JS?

A:
super is used to:

  • Access and call functions on an object’s parent class.
  • Must be used before this in derived class constructors.
class Parent {
  constructor(name) {
    this.name = name;
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name); // Calls Parent constructor
    this.age = age;
  }
}
Enter fullscreen mode Exit fullscreen mode

Q10. What will be the output of the following?

class Box {
  area() {
    return "Box area is 100";
  }
}

class Square extends Box {
  area() {
    return "Square area is 16";
  }
}

const obj = new Square();
console.log(obj.area());
Enter fullscreen mode Exit fullscreen mode

A:
Output: Square area is 16
➡ Because the child class method overrides the parent class method.

That’s a wrap on JavaScript Guide – Part 2!

Top comments (0)