Om Pandey
JavaScript

JavaScript

The Language of the Web

Master JavaScript - the world's most popular programming language. Build interactive websites, web applications, servers, mobile apps, and more. From zero to hero!

Runs Everywhere Dynamic & Fast Full Stack Huge Community

What You'll Learn

1

Introduction to JavaScript

JavaScript is a versatile, high-level programming language that powers the interactive web. Originally created for browsers, it now runs on servers (Node.js), mobile devices, desktop apps, and even IoT devices. It's the most used programming language in the world!

💡 Why JavaScript?

Universal: JavaScript is the only language that runs natively in all web browsers. Used by Netflix, Google, Facebook, Amazon, and virtually every website you visit!

🌐 JavaScript Ecosystem
🌐 Frontend
(React, Vue, Angular)
⚡ JavaScript
🖥️ Backend
(Node.js, Express)
What JavaScript Can Do:
  • Frontend: Interactive UIs, animations, form validation
  • Backend: APIs, servers, databases with Node.js
  • Mobile: React Native, Ionic for mobile apps
  • Desktop: Electron for desktop applications
2

Setup & Environment

1

Browser Console (Quickest Way)

Open any browser, press F12 or right-click → Inspect → Console tab

2

HTML File with Script

Create an HTML file and add JavaScript inside or link external file

index.html
HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My First JavaScript</title>
</head>
<body>
    <h1>Hello JavaScript!</h1>
    
    <!-- Inline JavaScript -->
    <script>
        console.log("Hello from inline script!");
    </script>
    
    <!-- External JavaScript (recommended) -->
    <script src="script.js"></script>
</body>
</html>
3

Install Node.js (For Backend/Local Development)

Download from nodejs.org to run JavaScript outside the browser

Terminal
$ # Check Node.js installation $ node --version v20.10.0 $ # Run JavaScript file $ node script.js Hello from JavaScript! $ # Interactive Node REPL $ node > console.log("Hello!") Hello! undefined

✅ Ready to Code!

You can now write JavaScript in the browser console, HTML files, or with Node.js!

3

Variables & Data Types

Declaring Variables

variables.js
// var - old way (function scoped, avoid using)
var oldWay = "Don't use var";

// let - for values that change (block scoped)
let age = 25;
age = 26;  // ✅ Can be reassigned

// const - for values that don't change (block scoped)
const name = "Om Pandey";
// name = "John";  // ❌ Error: Cannot reassign const

// const with objects/arrays - contents CAN change
const person = { name: "Om" };
person.name = "John";  // ✅ This works!
person.age = 25;       // ✅ Can add properties

// Naming conventions
let camelCase = "variables use camelCase";
const SCREAMING_SNAKE = "constants sometimes use this";
let _privateVar = "underscore for private";
let $specialVar = "dollar sign allowed";

⚠️ Best Practice

Always use const by default. Only use let when you need to reassign. Never use var!

Data Types

data-types.js
// ============ PRIMITIVE TYPES ============

// String - text
let firstName = "Om";
let lastName = 'Pandey';
let greeting = `Hello, ${firstName}!`;  // Template literal

// Number - integers and decimals
let integer = 42;
let decimal = 3.14;
let negative = -10;
let infinity = Infinity;
let notANumber = NaN;  // Not a Number

// BigInt - for very large numbers
let bigNumber = 9007199254740991n;

// Boolean - true or false
let isActive = true;
let isLoggedIn = false;

// Undefined - declared but not assigned
let notDefined;
console.log(notDefined);  // undefined

// Null - intentionally empty
let emptyValue = null;

// Symbol - unique identifier
let id = Symbol("id");


// ============ REFERENCE TYPES ============

// Object
let person = {
    name: "Om Pandey",
    age: 25,
    isStudent: true
};

// Array
let fruits = ["apple", "banana", "orange"];

// Function
function sayHello() {
    return "Hello!";
}


// ============ TYPEOF OPERATOR ============
console.log(typeof "Hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);        // "object" (JS bug!)
console.log(typeof {});          // "object"
console.log(typeof []);          // "object"
console.log(typeof function(){}); // "function"
Console Output
string number boolean undefined object object object function

String Methods

strings.js
const text = "Hello, JavaScript World!";

// Length
console.log(text.length);  // 24

// Access characters
console.log(text[0]);       // "H"
console.log(text.charAt(0)); // "H"

// Case conversion
console.log(text.toUpperCase());  // "HELLO, JAVASCRIPT WORLD!"
console.log(text.toLowerCase());  // "hello, javascript world!"

// Search
console.log(text.indexOf("JavaScript"));    // 7
console.log(text.includes("World"));        // true
console.log(text.startsWith("Hello"));      // true
console.log(text.endsWith("!"));            // true

// Extract
console.log(text.slice(7, 17));      // "JavaScript"
console.log(text.substring(7, 17));  // "JavaScript"

// Replace
console.log(text.replace("World", "Universe"));
// "Hello, JavaScript Universe!"

// Split into array
console.log(text.split(" "));  // ["Hello,", "JavaScript", "World!"]

// Trim whitespace
const messy = "  Hello World  ";
console.log(messy.trim());  // "Hello World"

// Template Literals (backticks)
const name = "Om";
const age = 25;
console.log(`My name is ${name} and I'm ${age} years old.`);
// "My name is Om and I'm 25 years old."

// Multi-line strings
const multiLine = `
    This is line 1
    This is line 2
    This is line 3
`;
4

Operators & Expressions

All Operators

operators.js
// ============ ARITHMETIC OPERATORS ============
let a = 10, b = 3;

console.log(a + b);   // 13 (addition)
console.log(a - b);   // 7  (subtraction)
console.log(a * b);   // 30 (multiplication)
console.log(a / b);   // 3.333... (division)
console.log(a % b);   // 1  (modulus - remainder)
console.log(a ** b);  // 1000 (exponentiation)

// Increment/Decrement
let x = 5;
console.log(x++);  // 5 (returns, then increments)
console.log(x);    // 6
console.log(++x);  // 7 (increments, then returns)


// ============ COMPARISON OPERATORS ============
console.log(5 == "5");    // true  (loose equality - type coercion)
console.log(5 === "5");   // false (strict equality - no coercion)
console.log(5 != "5");    // false
console.log(5 !== "5");   // true
console.log(5 > 3);       // true
console.log(5 < 3);       // false
console.log(5 >= 5);      // true
console.log(5 <= 4);      // false


// ============ LOGICAL OPERATORS ============
console.log(true && true);   // true (AND)
console.log(true && false);  // false
console.log(true || false);  // true (OR)
console.log(false || false); // false
console.log(!true);          // false (NOT)
console.log(!false);         // true


// ============ ASSIGNMENT OPERATORS ============
let num = 10;
num += 5;   // num = num + 5  → 15
num -= 3;   // num = num - 3  → 12
num *= 2;   // num = num * 2  → 24
num /= 4;   // num = num / 4  → 6
num %= 4;   // num = num % 4  → 2


// ============ TERNARY OPERATOR ============
const age = 20;
const status = age >= 18 ? "Adult" : "Minor";
console.log(status);  // "Adult"


// ============ NULLISH COALESCING (??) ============
const username = null;
const displayName = username ?? "Guest";
console.log(displayName);  // "Guest"


// ============ OPTIONAL CHAINING (?.) ============
const user = { profile: { name: "Om" } };
console.log(user?.profile?.name);     // "Om"
console.log(user?.settings?.theme);  // undefined (no error!)

💡 Always Use Strict Equality

Use === and !== instead of == and != to avoid unexpected type coercion bugs!

5

Control Flow

Conditionals

conditionals.js
// ============ IF / ELSE IF / ELSE ============
const score = 85;

if (score >= 90) {
    console.log("Grade: A");
} else if (score >= 80) {
    console.log("Grade: B");
} else if (score >= 70) {
    console.log("Grade: C");
} else {
    console.log("Grade: F");
}
// Output: "Grade: B"


// ============ SWITCH STATEMENT ============
const day = "Monday";

switch (day) {
    case "Monday":
        console.log("Start of the week!");
        break;
    case "Friday":
        console.log("TGIF!");
        break;
    case "Saturday":
    case "Sunday":
        console.log("Weekend!");
        break;
    default:
        console.log("Regular day");
}


// ============ TRUTHY & FALSY VALUES ============
// Falsy: false, 0, "", null, undefined, NaN
// Everything else is truthy

if ("Hello") console.log("Truthy!");  // Runs
if (0) console.log("Falsy!");          // Doesn't run
if ([]) console.log("Empty array is truthy!");  // Runs!
if ({}) console.log("Empty object is truthy!"); // Runs!

Loops

loops.js
// ============ FOR LOOP ============
for (let i = 0; i < 5; i++) {
    console.log(`Iteration: ${i}`);
}
// 0, 1, 2, 3, 4


// ============ WHILE LOOP ============
let count = 0;
while (count < 3) {
    console.log(`Count: ${count}`);
    count++;
}


// ============ DO-WHILE LOOP ============
let num = 0;
do {
    console.log(`Number: ${num}`);
    num++;
} while (num < 3);


// ============ FOR...OF (Arrays, Strings) ============
const fruits = ["apple", "banana", "orange"];
for (const fruit of fruits) {
    console.log(fruit);
}
// apple, banana, orange


// ============ FOR...IN (Objects) ============
const person = { name: "Om", age: 25, city: "Kathmandu" };
for (const key in person) {
    console.log(`${key}: ${person[key]}`);
}
// name: Om, age: 25, city: Kathmandu


// ============ BREAK & CONTINUE ============
for (let i = 0; i < 10; i++) {
    if (i === 3) continue;  // Skip 3
    if (i === 7) break;     // Stop at 7
    console.log(i);
}
// 0, 1, 2, 4, 5, 6
6

Functions

Functions are reusable blocks of code that perform specific tasks. JavaScript has multiple ways to define functions.

functions.js
// ============ FUNCTION DECLARATION ============
function greet(name) {
    return `Hello, ${name}!`;
}
console.log(greet("Om"));  // "Hello, Om!"


// ============ FUNCTION EXPRESSION ============
const add = function(a, b) {
    return a + b;
};
console.log(add(5, 3));  // 8


// ============ ARROW FUNCTIONS (ES6) ============
const multiply = (a, b) => {
    return a * b;
};

// Short form (implicit return)
const square = x => x * x;
const sum = (a, b) => a + b;

console.log(square(4));    // 16
console.log(sum(2, 3));    // 5


// ============ DEFAULT PARAMETERS ============
function welcome(name = "Guest", greeting = "Hello") {
    return `${greeting}, ${name}!`;
}
console.log(welcome());              // "Hello, Guest!"
console.log(welcome("Om"));          // "Hello, Om!"
console.log(welcome("Om", "Hi"));   // "Hi, Om!"


// ============ REST PARAMETERS ============
function sumAll(...numbers) {
    return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sumAll(1, 2, 3, 4, 5));  // 15


// ============ CALLBACK FUNCTIONS ============
function processData(data, callback) {
    const result = data.toUpperCase();
    callback(result);
}

processData("hello", (result) => {
    console.log(result);  // "HELLO"
});


// ============ HIGHER-ORDER FUNCTIONS ============
function createMultiplier(multiplier) {
    return (number) => number * multiplier;
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15


// ============ IIFE (Immediately Invoked Function Expression) ============
(function() {
    console.log("I run immediately!");
})();

// Arrow function IIFE
(() => {
    console.log("Arrow IIFE!");
})();

💡 Arrow Functions vs Regular Functions

Arrow functions don't have their own this binding. Use regular functions for object methods and constructors, arrow functions for callbacks!

7

Arrays & Objects

Arrays

arrays.js
// ============ CREATING ARRAYS ============
const fruits = ["apple", "banana", "orange"];
const numbers = new Array(1, 2, 3, 4, 5);
const mixed = [1, "two", true, { name: "Om" }];


// ============ ACCESSING ELEMENTS ============
console.log(fruits[0]);         // "apple"
console.log(fruits[fruits.length - 1]);  // "orange" (last)
console.log(fruits.at(-1));      // "orange" (ES2022)


// ============ MODIFYING ARRAYS ============
fruits.push("mango");       // Add to end
fruits.pop();               // Remove from end
fruits.unshift("grape");    // Add to beginning
fruits.shift();             // Remove from beginning
fruits.splice(1, 1, "kiwi"); // Remove 1 at index 1, add "kiwi"


// ============ ARRAY METHODS ============
const nums = [1, 2, 3, 4, 5];

// map - transform each element
const doubled = nums.map(n => n * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]

// filter - keep elements that pass test
const evens = nums.filter(n => n % 2 === 0);
console.log(evens);  // [2, 4]

// reduce - reduce to single value
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(sum);  // 15

// find - find first matching element
const found = nums.find(n => n > 3);
console.log(found);  // 4

// findIndex - find index of first match
const index = nums.findIndex(n => n > 3);
console.log(index);  // 3

// some - check if any element passes
console.log(nums.some(n => n > 4));  // true

// every - check if all elements pass
console.log(nums.every(n => n > 0)); // true

// includes - check if element exists
console.log(nums.includes(3));  // true

// sort - sort array (mutates!)
const unsorted = [3, 1, 4, 1, 5];
unsorted.sort((a, b) => a - b);  // [1, 1, 3, 4, 5]

// reverse - reverse array (mutates!)
nums.reverse();  // [5, 4, 3, 2, 1]

// join - convert to string
console.log(["a", "b", "c"].join("-"));  // "a-b-c"

// flat - flatten nested arrays
const nested = [[1, 2], [3, 4], [5]];
console.log(nested.flat());  // [1, 2, 3, 4, 5]


// ============ SPREAD OPERATOR ============
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];  // [1, 2, 3, 4, 5, 6]
const copy = [...arr1];              // Clone array


// ============ DESTRUCTURING ============
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first);  // 1
console.log(second); // 2
console.log(rest);   // [3, 4, 5]

Objects

objects.js
// ============ CREATING OBJECTS ============
const person = {
    firstName: "Om",
    lastName: "Pandey",
    age: 25,
    isStudent: true,
    skills: ["JavaScript", "Python", "React"],
    address: {
        city: "Kathmandu",
        country: "Nepal"
    },
    // Method
    getFullName() {
        return `${this.firstName} ${this.lastName}`;
    }
};


// ============ ACCESSING PROPERTIES ============
console.log(person.firstName);       // "Om" (dot notation)
console.log(person["lastName"]);     // "Pandey" (bracket notation)
console.log(person.address.city);    // "Kathmandu"
console.log(person.getFullName());   // "Om Pandey"


// ============ MODIFYING OBJECTS ============
person.email = "[email protected]";  // Add property
person.age = 26;                  // Update property
delete person.isStudent;          // Delete property


// ============ OBJECT METHODS ============
console.log(Object.keys(person));    // ["firstName", "lastName", ...]
console.log(Object.values(person));  // ["Om", "Pandey", ...]
console.log(Object.entries(person)); // [["firstName", "Om"], ...]

// Check if property exists
console.log("firstName" in person);           // true
console.log(person.hasOwnProperty("age"));  // true


// ============ SPREAD OPERATOR ============
const personCopy = { ...person };                   // Clone object
const updated = { ...person, age: 30 };              // Clone and update
const merged = { ...person, ...{ job: "Developer" }}; // Merge objects


// ============ DESTRUCTURING ============
const { firstName, lastName, age } = person;
console.log(firstName);  // "Om"

// With renaming
const { firstName: fName, lastName: lName } = person;

// With default values
const { job = "Unknown" } = person;

// Nested destructuring
const { address: { city } } = person;
console.log(city);  // "Kathmandu"


// ============ SHORTHAND PROPERTIES ============
const name = "Om";
const city = "Kathmandu";
const user = { name, city };  // Same as { name: name, city: city }


// ============ COMPUTED PROPERTY NAMES ============
const key = "dynamicKey";
const obj = {
    [key]: "Dynamic Value",
    ["key" + 1]: "Key 1"
};
console.log(obj.dynamicKey);  // "Dynamic Value"
8

DOM Manipulation

The Document Object Model (DOM) is how JavaScript interacts with HTML elements on a webpage.

🌳 DOM Tree Structure
document
html
body
div, p, etc.
dom.js
// ============ SELECTING ELEMENTS ============

// Single element
const heading = document.getElementById("main-heading");
const firstBtn = document.querySelector(".btn");  // First match
const nav = document.querySelector("nav");

// Multiple elements
const allBtns = document.querySelectorAll(".btn");        // NodeList
const allParas = document.getElementsByClassName("para"); // HTMLCollection
const allDivs = document.getElementsByTagName("div");


// ============ MODIFYING CONTENT ============

// Text content (plain text)
heading.textContent = "New Heading";

// Inner HTML (can include tags)
heading.innerHTML = "<span>Styled</span> Heading";

// Value (for inputs)
const input = document.querySelector("input");
console.log(input.value);
input.value = "New value";


// ============ MODIFYING STYLES ============

// Inline styles
heading.style.color = "blue";
heading.style.fontSize = "2rem";
heading.style.backgroundColor = "#f0f0f0";

// CSS Classes
heading.classList.add("active");
heading.classList.remove("hidden");
heading.classList.toggle("visible");
heading.classList.contains("active");  // true/false
heading.classList.replace("old", "new");


// ============ ATTRIBUTES ============
const link = document.querySelector("a");

link.getAttribute("href");
link.setAttribute("href", "https://example.com");
link.removeAttribute("target");
link.hasAttribute("href");  // true/false

// Data attributes
// <div data-user-id="123" data-role="admin">
const div = document.querySelector("div");
console.log(div.dataset.userId);  // "123"
console.log(div.dataset.role);    // "admin"


// ============ CREATING ELEMENTS ============
const newDiv = document.createElement("div");
newDiv.textContent = "I'm new!";
newDiv.className = "card";
newDiv.id = "new-card";

// Add to DOM
document.body.appendChild(newDiv);           // Add as last child
document.body.prepend(newDiv);               // Add as first child
heading.insertAdjacentElement("afterend", newDiv); // After heading

// Remove from DOM
newDiv.remove();
// Or: parent.removeChild(newDiv);


// ============ TRAVERSING DOM ============
const element = document.querySelector(".item");

element.parentElement;         // Parent
element.children;              // Child elements
element.firstElementChild;     // First child element
element.lastElementChild;      // Last child element
element.nextElementSibling;    // Next sibling
element.previousElementSibling; // Previous sibling
element.closest(".container");  // Closest ancestor matching selector
9

Events

Events are actions that happen in the browser - clicks, key presses, form submissions, etc.

events.js
// ============ ADDING EVENT LISTENERS ============
const button = document.querySelector("#myBtn");

// Method 1: addEventListener (recommended)
button.addEventListener("click", function(event) {
    console.log("Button clicked!");
    console.log(event);  // Event object
});

// Arrow function version
button.addEventListener("click", (e) => {
    console.log("Clicked!", e.target);
});

// Method 2: onclick property (older way)
button.onclick = () => console.log("Clicked!");


// ============ COMMON EVENTS ============

// Mouse events
element.addEventListener("click", handler);
element.addEventListener("dblclick", handler);
element.addEventListener("mouseenter", handler);
element.addEventListener("mouseleave", handler);
element.addEventListener("mousemove", handler);

// Keyboard events
document.addEventListener("keydown", (e) => {
    console.log(e.key);      // "Enter", "a", "ArrowUp"
    console.log(e.code);     // "Enter", "KeyA", "ArrowUp"
    console.log(e.ctrlKey);  // true if Ctrl held
});

// Form events
form.addEventListener("submit", (e) => {
    e.preventDefault();  // Prevent form submission
    console.log("Form submitted!");
});

input.addEventListener("input", (e) => {
    console.log(e.target.value);  // Real-time input value
});

input.addEventListener("change", handler);  // On blur after change
input.addEventListener("focus", handler);
input.addEventListener("blur", handler);

// Window events
window.addEventListener("load", handler);
window.addEventListener("scroll", handler);
window.addEventListener("resize", handler);


// ============ EVENT OBJECT ============
button.addEventListener("click", (e) => {
    e.target;           // Element that triggered event
    e.currentTarget;    // Element listener is attached to
    e.type;             // "click"
    e.clientX;          // Mouse X position in viewport
    e.clientY;          // Mouse Y position in viewport
    e.preventDefault();  // Prevent default behavior
    e.stopPropagation(); // Stop event bubbling
});


// ============ EVENT DELEGATION ============
// Instead of adding listeners to many elements,
// add one listener to parent

const list = document.querySelector("ul");

list.addEventListener("click", (e) => {
    if (e.target.tagName === "LI") {
        console.log("List item clicked:", e.target.textContent);
    }
});


// ============ REMOVE EVENT LISTENER ============
function handleClick() {
    console.log("Clicked!");
}

button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);
10

Async JavaScript

JavaScript is single-threaded but can handle asynchronous operations using callbacks, promises, and async/await.

async.js
// ============ CALLBACKS ============
function fetchData(callback) {
    setTimeout(() => {
        const data = { name: "Om", age: 25 };
        callback(data);
    }, 1000);
}

fetchData((data) => {
    console.log(data);  // After 1 second: { name: "Om", age: 25 }
});


// ============ PROMISES ============
const myPromise = new Promise((resolve, reject) => {
    const success = true;
    
    setTimeout(() => {
        if (success) {
            resolve("Data fetched successfully!");
        } else {
            reject("Error fetching data");
        }
    }, 1000);
});

// Using the promise
myPromise
    .then((result) => {
        console.log(result);
        return "Next step";
    })
    .then((nextResult) => {
        console.log(nextResult);
    })
    .catch((error) => {
        console.error(error);
    })
    .finally(() => {
        console.log("Done!");
    });


// ============ ASYNC / AWAIT ============
async function fetchUser() {
    try {
        const response = await fetch("https://api.example.com/user");
        const data = await response.json();
        console.log(data);
        return data;
    } catch (error) {
        console.error("Error:", error);
    }
}

// Arrow function version
const fetchPosts = async () => {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    const posts = await response.json();
    return posts;
};


// ============ FETCH API ============
// GET request
fetch("https://api.example.com/users")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

// POST request
fetch("https://api.example.com/users", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        name: "Om Pandey",
        email: "[email protected]"
    })
})
.then(response => response.json())
.then(data => console.log(data));


// ============ PROMISE METHODS ============
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

// Wait for all to complete
Promise.all([promise1, promise2, promise3])
    .then(values => console.log(values));  // [1, 2, 3]

// Race - first to complete wins
Promise.race([promise1, promise2])
    .then(value => console.log(value));  // 1

// allSettled - wait for all (success or fail)
Promise.allSettled([promise1, Promise.reject("error")])
    .then(results => console.log(results));

💡 Pro Tip

Always use async/await with try/catch for cleaner, more readable asynchronous code!

11

ES6+ Features

es6-features.js
// ============ MODULES (import/export) ============

// math.js - exporting
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export default class Calculator { }

// app.js - importing
import Calculator, { PI, add } from './math.js';
import * as math from './math.js';  // Import all


// ============ CLASSES ============
class Person {
    // Private field (ES2022)
    #ssn;
    
    // Static property
    static species = "Homo sapiens";
    
    constructor(name, age) {
        this.name = name;
        this.age = age;
        this.#ssn = "123-45-6789";
    }
    
    // Method
    greet() {
        return `Hello, I'm ${this.name}`;
    }
    
    // Getter
    get info() {
        return `${this.name}, ${this.age}`;
    }
    
    // Setter
    set info(value) {
        [this.name, this.age] = value.split(", ");
    }
    
    // Static method
    static create(name) {
        return new Person(name, 0);
    }
}

// Inheritance
class Student extends Person {
    constructor(name, age, grade) {
        super(name, age);  // Call parent constructor
        this.grade = grade;
    }
    
    study() {
        return `${this.name} is studying`;
    }
}

const student = new Student("Om", 25, "A");
console.log(student.greet());   // "Hello, I'm Om"
console.log(student.study());   // "Om is studying"


// ============ MAP & SET ============

// Map - key-value pairs (any type as key)
const map = new Map();
map.set("name", "Om");
map.set(1, "one");
map.set({ id: 1 }, "object key");

console.log(map.get("name"));  // "Om"
console.log(map.has(1));        // true
console.log(map.size);        // 3

// Set - unique values only
const set = new Set([1, 2, 2, 3, 3]);
console.log(set);  // Set { 1, 2, 3 }
set.add(4);
set.delete(1);
set.has(2);  // true

// Remove duplicates from array
const unique = [...new Set([1, 1, 2, 2, 3])];  // [1, 2, 3]


// ============ SYMBOLS ============
const id = Symbol("id");
const id2 = Symbol("id");
console.log(id === id2);  // false (always unique)


// ============ ITERATORS & GENERATORS ============
function* numberGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = numberGenerator();
console.log(gen.next());  // { value: 1, done: false }
console.log(gen.next());  // { value: 2, done: false }


// ============ PROXY ============
const target = { name: "Om" };
const handler = {
    get(obj, prop) {
        return prop in obj ? obj[prop] : "Property not found";
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);     // "Om"
console.log(proxy.unknown);  // "Property not found"
12

Advanced Topics

Local Storage

storage.js
// ============ LOCAL STORAGE ============
// Persists even after browser closes
// Store data
localStorage.setItem("username", "Om");
localStorage.setItem("theme", "dark");

// Store objects (must stringify)
const user = { name: "Om", age: 25 };
localStorage.setItem("user", JSON.stringify(user));

// Retrieve data
const username = localStorage.getItem("username");
const savedUser = JSON.parse(localStorage.getItem("user"));

// Remove item
localStorage.removeItem("username");

// Clear all
localStorage.clear();

// Check length
console.log(localStorage.length);


// ============ SESSION STORAGE ============
// Same API, but clears when tab closes

sessionStorage.setItem("tempData", "value");
sessionStorage.getItem("tempData");
sessionStorage.removeItem("tempData");
sessionStorage.clear();

Error Handling

errors.js
// ============ TRY / CATCH / FINALLY ============
try {
    // Code that might throw an error
    const data = JSON.parse("invalid json");
} catch (error) {
    // Handle the error
    console.error("Error:", error.message);
} finally {
    // Always runs
    console.log("Cleanup complete");
}


// ============ THROW CUSTOM ERRORS ============
function divide(a, b) {
    if (b === 0) {
        throw new Error("Cannot divide by zero!");
    }
    return a / b;
}

try {
    divide(10, 0);
} catch (error) {
    console.error(error.message);  // "Cannot divide by zero!"
}


// ============ ERROR TYPES ============
new Error("Generic error");
new TypeError("Type error");
new ReferenceError("Reference error");
new SyntaxError("Syntax error");
new RangeError("Range error");


// ============ CUSTOM ERROR CLASS ============
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }
}

throw new ValidationError("Invalid email format");

Regular Expressions

regex.js
// ============ CREATING REGEX ============
const regex1 = /hello/i;              // Literal (i = case insensitive)
const regex2 = new RegExp("hello", "i"); // Constructor


// ============ REGEX METHODS ============
const text = "Hello World, hello there!";

// test() - returns true/false
console.log(/hello/i.test(text));  // true

// match() - returns matches array
console.log(text.match(/hello/gi));  // ["Hello", "hello"]

// replace() - replace matches
console.log(text.replace(/hello/gi, "Hi"));  // "Hi World, Hi there!"

// split() - split by pattern
console.log("a,b;c|d".split(/[,;|]/));  // ["a", "b", "c", "d"]

// search() - returns index of first match
console.log(text.search(/world/i));  // 6


// ============ COMMON PATTERNS ============
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const phoneRegex = /^\d{10}$/;
const urlRegex = /^(https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/;
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;

// Validation examples
console.log(emailRegex.test("[email protected]"));  // true
console.log(phoneRegex.test("1234567890"));     // true


// ============ REGEX CHEATSHEET ============
// .     Any character except newline
// \d    Digit (0-9)
// \D    Not a digit
// \w    Word character (a-z, A-Z, 0-9, _)
// \W    Not a word character
// \s    Whitespace
// \S    Not whitespace
// ^     Start of string
// $     End of string
// *     0 or more
// +     1 or more
// ?     0 or 1
// {n}   Exactly n times
// {n,m} Between n and m times
// [abc] Character set
// [^abc] Negated set
// (abc) Capture group
// a|b   a or b

Date & Time

date-time.js
// ============ CREATING DATES ============
const now = new Date();
const specific = new Date("2025-01-25");
const withTime = new Date("2025-01-25T10:30:00");
const fromParts = new Date(2025, 0, 25);  // Month is 0-indexed!
const timestamp = new Date(1706140800000);  // From milliseconds


// ============ GETTING DATE PARTS ============
const date = new Date();

console.log(date.getFullYear());   // 2025
console.log(date.getMonth());      // 0-11 (January = 0)
console.log(date.getDate());       // 1-31 (day of month)
console.log(date.getDay());        // 0-6 (Sunday = 0)
console.log(date.getHours());      // 0-23
console.log(date.getMinutes());    // 0-59
console.log(date.getSeconds());    // 0-59
console.log(date.getTime());       // Milliseconds since Jan 1, 1970


// ============ SETTING DATE PARTS ============
date.setFullYear(2026);
date.setMonth(6);        // July
date.setDate(15);
date.setHours(10);
date.setMinutes(30);


// ============ FORMATTING DATES ============
const d = new Date();

console.log(d.toString());       // Full string
console.log(d.toDateString());   // "Sat Jan 25 2025"
console.log(d.toTimeString());   // "10:30:00 GMT+0545"
console.log(d.toISOString());    // "2025-01-25T04:45:00.000Z"
console.log(d.toLocaleDateString());  // "1/25/2025"
console.log(d.toLocaleTimeString());  // "10:30:00 AM"

// Custom formatting with Intl
const options = { 
    weekday: 'long', 
    year: 'numeric', 
    month: 'long', 
    day: 'numeric' 
};
console.log(d.toLocaleDateString('en-US', options));
// "Saturday, January 25, 2025"


// ============ DATE CALCULATIONS ============
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);

// Difference between dates
const date1 = new Date("2025-01-01");
const date2 = new Date("2025-12-31");
const diffMs = date2 - date1;
const diffDays = diffMs / (1000 * 60 * 60 * 24);
console.log(diffDays);  // 364

JSON

json.js
// ============ PARSE JSON (String → Object) ============
const jsonString = '{"name": "Om", "age": 25, "skills": ["JS", "Python"]}';
const obj = JSON.parse(jsonString);

console.log(obj.name);    // "Om"
console.log(obj.skills);  // ["JS", "Python"]


// ============ STRINGIFY (Object → String) ============
const user = {
    name: "Om Pandey",
    age: 25,
    isActive: true,
    skills: ["JavaScript", "React"]
};

const json = JSON.stringify(user);
console.log(json);
// '{"name":"Om Pandey","age":25,"isActive":true,"skills":["JavaScript","React"]}'

// Pretty print with indentation
const prettyJson = JSON.stringify(user, null, 2);
console.log(prettyJson);

// Selective stringify with replacer
const filtered = JSON.stringify(user, ["name", "age"]);
console.log(filtered);  // '{"name":"Om Pandey","age":25}'


// ============ DEEP CLONE WITH JSON ============
const original = { a: 1, b: { c: 2 } };
const clone = JSON.parse(JSON.stringify(original));
clone.b.c = 999;
console.log(original.b.c);  // 2 (unchanged!)

Timers

timers.js
// ============ setTimeout ============
// Execute once after delay

const timeoutId = setTimeout(() => {
    console.log("This runs after 2 seconds");
}, 2000);

// Cancel timeout
clearTimeout(timeoutId);


// ============ setInterval ============
// Execute repeatedly at interval

let count = 0;
const intervalId = setInterval(() => {
    count++;
    console.log(`Count: ${count}`);
    
    if (count >= 5) {
        clearInterval(intervalId);  // Stop after 5
    }
}, 1000);


// ============ requestAnimationFrame ============
// For smooth animations (60fps)

function animate() {
    // Update animation
    element.style.left = `${position}px`;
    position++;
    
    if (position < 500) {
        requestAnimationFrame(animate);
    }
}

requestAnimationFrame(animate);


// ============ DEBOUNCE FUNCTION ============
function debounce(func, delay) {
    let timeoutId;
    return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    };
}

// Usage: Only fires after user stops typing for 300ms
const handleSearch = debounce((query) => {
    console.log("Searching for:", query);
}, 300);

input.addEventListener("input", (e) => handleSearch(e.target.value));


// ============ THROTTLE FUNCTION ============
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// Usage: Only fires once every 100ms
window.addEventListener("scroll", throttle(() => {
    console.log("Scrolling...");
}, 100));

Closures & Scope

closures.js
// ============ SCOPE ============

// Global scope
var globalVar = "I'm global";

function outer() {
    // Function scope
    let outerVar = "I'm in outer";
    
    if (true) {
        // Block scope
        let blockVar = "I'm in block";
        const constVar = "Also block scoped";
        var varVar = "I'm function scoped!";  // var ignores block!
    }
    
    console.log(varVar);  // ✅ Works
    // console.log(blockVar);  // ❌ Error: not defined
}


// ============ CLOSURES ============
// A function that remembers its outer scope

function createCounter() {
    let count = 0;  // Private variable
    
    return {
        increment() {
            count++;
            return count;
        },
        decrement() {
            count--;
            return count;
        },
        getCount() {
            return count;
        }
    };
}

const counter = createCounter();
console.log(counter.increment());  // 1
console.log(counter.increment());  // 2
console.log(counter.decrement());  // 1
// console.log(count);  // ❌ Error: count is private!


// ============ PRACTICAL CLOSURE EXAMPLES ============

// Private data
function createBankAccount(initialBalance) {
    let balance = initialBalance;
    
    return {
        deposit(amount) {
            balance += amount;
            return balance;
        },
        withdraw(amount) {
            if (amount <= balance) {
                balance -= amount;
                return balance;
            }
            return "Insufficient funds";
        },
        getBalance() {
            return balance;
        }
    };
}

const account = createBankAccount(100);
account.deposit(50);   // 150
account.withdraw(30);  // 120


// Function factories
function createGreeter(greeting) {
    return function(name) {
        return `${greeting}, ${name}!`;
    };
}

const sayHello = createGreeter("Hello");
const sayHi = createGreeter("Hi");

console.log(sayHello("Om"));  // "Hello, Om!"
console.log(sayHi("Om"));     // "Hi, Om!"

this Keyword

this-keyword.js
// ============ 'this' IN DIFFERENT CONTEXTS ============

// 1. Global context
console.log(this);  // window (browser) or global (Node)

// 2. Object method
const user = {
    name: "Om",
    greet() {
        console.log(`Hello, I'm ${this.name}`);
    }
};
user.greet();  // "Hello, I'm Om" - this = user

// 3. Arrow function (inherits from parent)
const person = {
    name: "Om",
    greet: () => {
        console.log(this.name);  // undefined - this = window!
    },
    greetCorrect() {
        const inner = () => {
            console.log(this.name);  // "Om" - inherits from greetCorrect
        };
        inner();
    }
};

// 4. Constructor function
function Person(name) {
    this.name = name;  // this = new instance
}


// ============ EXPLICIT BINDING ============

function introduce(greeting) {
    console.log(`${greeting}, I'm ${this.name}`);
}

const om = { name: "Om" };
const john = { name: "John" };

// call - invoke immediately with arguments
introduce.call(om, "Hello");    // "Hello, I'm Om"
introduce.call(john, "Hi");     // "Hi, I'm John"

// apply - same as call but with array of arguments
introduce.apply(om, ["Hey"]);   // "Hey, I'm Om"

// bind - returns new function with bound 'this'
const omIntro = introduce.bind(om);
omIntro("Howdy");              // "Howdy, I'm Om"


// ============ COMMON PITFALL & FIX ============

const obj = {
    name: "Om",
    handleClick() {
        console.log(this.name);
    }
};

// Problem: 'this' is lost when passing method as callback
// button.addEventListener("click", obj.handleClick); // this = button!

// Solutions:
// 1. Arrow function wrapper
button.addEventListener("click", () => obj.handleClick());

// 2. Bind
button.addEventListener("click", obj.handleClick.bind(obj));

🚀 Congratulations!

You've mastered JavaScript from zero to hero! You're now ready to build interactive websites, web apps, and even backend services. Keep building!