Tutorials / JavaScript

JavaScript JS

From Basics to Advanced - Complete Guide

1 Introduction to JavaScript

JavaScript is the programming language of the web. It adds interactivity to websites - handling clicks, validating forms, fetching data, creating animations, and much more. Unlike HTML (structure) and CSS (style), JavaScript provides behavior.

JavaScript in Web Development
HTML
Structure
+
CSS
Style
+
JavaScript
Behavior
=
Interactive
Website

🔑 Where JavaScript Runs

Browser: Runs in Chrome, Firefox, Safari - makes websites interactive
Server (Node.js): Runs on servers - powers backends, APIs
Mobile: React Native, Ionic - builds mobile apps
Desktop: Electron - builds desktop apps (VS Code, Slack)

JavaScript - Hello World
// This is a single-line comment

/*
   This is a multi-line comment.
   Use for longer explanations.
*/

// Print to browser console (F12 to open)
console.log("Hello, World!");

// Print multiple values
console.log("Name:", "Alice", "Age:", 25);

// Show alert popup (avoid in production)
alert("Welcome to JavaScript!");
▶ CONSOLE OUTPUT
Hello, World!
Name: Alice Age: 25

2 Variables

Variables store data values. JavaScript has three ways to declare variables: let, const, and var. Modern JavaScript prefers let and const.

Variable Declaration Types
let
Can reassign
const
Cannot reassign
var
Old way (avoid)
JavaScript - Variables
// LET - value can change later
let age = 25;
console.log("Age:", age);    // Age: 25

age = 26;                      // ✓ Allowed - reassigning
console.log("New age:", age); // New age: 26

// CONST - value cannot change (use by default!)
const name = "Alice";
console.log("Name:", name);   // Name: Alice

// name = "Bob";  // ✗ ERROR! Cannot reassign const

// CONST with objects - properties CAN change
const person = { name: "Alice", age: 25 };
person.age = 26;              // ✓ Allowed - modifying property
console.log(person);           // { name: "Alice", age: 26 }

// VAR - old way, has scoping issues (avoid!)
var oldVariable = "Don't use var";

// Good naming conventions
let firstName = "John";       // camelCase (recommended)
let is_active = true;         // snake_case (less common)
const MAX_SIZE = 100;         // SCREAMING_CASE for constants
▶ CONSOLE OUTPUT
Age: 25
New age: 26
Name: Alice
{ name: "Alice", age: 26 }

💡 Best Practice

Use const by default. Only use let when you know the value will change. Never use var in modern JavaScript.

3 Data Types

JavaScript has several built-in data types. Understanding them is crucial because different types behave differently and support different operations.

JavaScript - Data Types
// STRING - text in quotes
let greeting = "Hello";           // Double quotes
let name = 'Alice';               // Single quotes
let message = `Hi, ${name}!`;     // Template literal (backticks)
console.log(message);              // Hi, Alice!

// NUMBER - integers and decimals
let age = 25;
let price = 19.99;
let negative = -10;
console.log(age + price);          // 44.99

// BOOLEAN - true or false
let isLoggedIn = true;
let hasPermission = false;
console.log(isLoggedIn);           // true

// UNDEFINED - declared but no value
let undefinedVar;
console.log(undefinedVar);         // undefined

// NULL - intentionally empty
let emptyValue = null;
console.log(emptyValue);           // null

// ARRAY - ordered list of values
let colors = ["red", "green", "blue"];
console.log(colors[0]);            // red (index 0)
console.log(colors.length);        // 3

// OBJECT - key-value pairs
let person = {
    name: "Alice",
    age: 25,
    isStudent: true
};
console.log(person.name);          // Alice
console.log(person["age"]);        // 25

// Check type with typeof
console.log(typeof greeting);      // string
console.log(typeof age);           // number
console.log(typeof isLoggedIn);    // boolean
console.log(typeof colors);        // object (arrays are objects)
▶ CONSOLE OUTPUT
Hi, Alice!
44.99
true
undefined
null
red
3
Alice
25
string
number
boolean
object

4 Operators

Operators perform operations on values. JavaScript has arithmetic, comparison, logical, and assignment operators.

JavaScript - Operators
// ARITHMETIC OPERATORS
let a = 10, b = 3;

console.log(a + b);   // Addition: 13
console.log(a - b);   // Subtraction: 7
console.log(a * b);   // Multiplication: 30
console.log(a / b);   // Division: 3.333...
console.log(a % b);   // Modulo (remainder): 1
console.log(a ** b);  // Exponent: 1000

// INCREMENT / DECREMENT
let x = 5;
x++;  // x = 6 (increment)
x--;  // x = 5 (decrement)

// COMPARISON OPERATORS
console.log(5 == "5");   // true (loose equality, converts type)
console.log(5 === "5");  // false (strict equality, same type)
console.log(5 != "5");   // false
console.log(5 !== "5");  // true (strict not equal)
console.log(5 > 3);     // true
console.log(5 >= 5);    // true
console.log(3 < 5);     // true

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

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

// TERNARY OPERATOR (shorthand if/else)
let age = 20;
let status = age >= 18 ? "Adult" : "Minor";
console.log(status);  // "Adult"
▶ CONSOLE OUTPUT
13
7
30
3.3333333333333335
1
1000
true
false
Adult

⚠️ Always Use === Instead of ==

The == operator converts types before comparing, leading to unexpected results like 0 == "" being true. Always use === for predictable comparisons.

5 Conditionals (If/Else)

Conditionals let your code make decisions. The code inside an if block only runs if the condition is true.

If/Else Decision Flow
TRUE
Run if block
|
FALSE
Run else block
JavaScript - Conditionals
const age = 20;
const score = 85;

// Simple if
if (age >= 18) {
    console.log("You are an adult");
}

// If-else
if (score >= 60) {
    console.log("You passed!");
} else {
    console.log("You failed.");
}

// If-else if-else chain
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");
}

// Ternary operator (shorthand if-else)
const status = age >= 18 ? "Adult" : "Minor";
console.log("Status:", status);

// Logical operators
const hasID = true;
const hasTicket = true;

// AND (&&) - both must be true
if (hasID && hasTicket) {
    console.log("Entry allowed");
}

// OR (||) - at least one must be true
if (age < 12 || age > 65) {
    console.log("Discount applies");
}
▶ CONSOLE OUTPUT
You are an adult
You passed!
Grade: B
Status: Adult
Entry allowed

5 Loops

Loops execute code repeatedly. Use for when you know how many times, while for unknown iterations, and for...of for arrays.

JavaScript - Loops
// FOR loop - when you know the count
console.log("=== FOR Loop ===");
for (let i = 1; i <= 5; i++) {
    console.log(`Count: ${i}`);
}

// FOR...OF loop - iterate over arrays
console.log("=== FOR...OF Loop ===");
const fruits = ["Apple", "Banana", "Cherry"];
for (const fruit of fruits) {
    console.log(`Fruit: ${fruit}`);
}

// WHILE loop - when count is unknown
console.log("=== WHILE Loop ===");
let countdown = 3;
while (countdown > 0) {
    console.log(`${countdown}...`);
    countdown--;
}
console.log("Liftoff! 🚀");

// forEach - array method for iteration
console.log("=== forEach ===");
fruits.forEach((fruit, index) => {
    console.log(`${index}: ${fruit}`);
});
▶ CONSOLE OUTPUT
=== FOR Loop ===
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
=== FOR...OF Loop ===
Fruit: Apple
Fruit: Banana
Fruit: Cherry
=== WHILE Loop ===
3...
2...
1...
Liftoff! 🚀
=== forEach ===
0: Apple
1: Banana
2: Cherry

6 Functions

Functions are reusable blocks of code. They can accept inputs (parameters), perform operations, and return outputs. Functions are fundamental to JavaScript.

Function Flow
Input
Parameters
Process
Function Body
Output
Return Value
JavaScript - Functions
// Basic function declaration
function greet() {
    console.log("Hello!");
}
greet();  // Call the function

// Function with parameters
function greetPerson(name) {
    console.log(`Hello, ${name}!`);
}
greetPerson("Alice");
greetPerson("Bob");

// Function with return value
function add(a, b) {
    return a + b;
}
const sum = add(5, 3);
console.log("Sum:", sum);

// Default parameters
function greetWithDefault(name = "Guest") {
    console.log(`Welcome, ${name}!`);
}
greetWithDefault();         // Uses default
greetWithDefault("Alice"); // Uses provided value

// ARROW FUNCTION (modern ES6+ syntax)
const multiply = (a, b) => {
    return a * b;
};
console.log("Multiply:", multiply(4, 5));

// Arrow function shorthand (single expression)
const square = (n) => n * n;
console.log("Square of 4:", square(4));

// Even shorter for single parameter
const double = n => n * 2;
console.log("Double of 7:", double(7));
▶ CONSOLE OUTPUT
Hello!
Hello, Alice!
Hello, Bob!
Sum: 8
Welcome, Guest!
Welcome, Alice!
Multiply: 20
Square of 4: 16
Double of 7: 14

8 Arrow Functions

Arrow functions provide a shorter syntax for writing functions. They're especially useful for callbacks and one-liners.

JavaScript - Arrow Functions
// Traditional function
function add(a, b) {
    return a + b;
}

// Arrow function equivalent
const addArrow = (a, b) => {
    return a + b;
};

// Shorter: implicit return (single expression)
const addShort = (a, b) => a + b;

// Single parameter: no parentheses needed
const double = n => n * 2;

// No parameters: empty parentheses
const greet = () => "Hello!";

// Usage
console.log(add(2, 3));       // 5
console.log(addArrow(2, 3));  // 5
console.log(addShort(2, 3));  // 5
console.log(double(5));       // 10
console.log(greet());         // "Hello!"

// Perfect for array methods!
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map(n => n * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]

const evens = numbers.filter(n => n % 2 === 0);
console.log(evens);    // [2, 4]
▶ CONSOLE OUTPUT
5
5
5
10
Hello!
[2, 4, 6, 8, 10]
[2, 4]

💡 When to Use Arrow Functions

✓ Callbacks: array.map(x => x * 2)
✓ Short one-liners
✗ Object methods (use regular functions for this)

9 Arrays

Arrays store multiple values in a single variable. They're ordered collections where each item has an index starting from 0.

JavaScript - Arrays Basics
// Creating arrays
const fruits = ["apple", "banana", "orange"];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, "two", true, null];

// Accessing elements (0-indexed)
console.log(fruits[0]);    // "apple"
console.log(fruits[2]);    // "orange"
console.log(fruits.length); // 3

// Modifying elements
fruits[1] = "mango";
console.log(fruits);  // ["apple", "mango", "orange"]

// Adding elements
fruits.push("grape");      // Add to end
fruits.unshift("kiwi");    // Add to beginning

// Removing elements
fruits.pop();               // Remove from end
fruits.shift();             // Remove from beginning

// Finding elements
console.log(fruits.indexOf("mango"));   // 1 (index)
console.log(fruits.includes("apple")); // true

// Slicing (does not modify original)
const nums = [1, 2, 3, 4, 5];
console.log(nums.slice(1, 4));  // [2, 3, 4]

// Joining arrays
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2];  // [1, 2, 3, 4]

// Looping through arrays
for (const fruit of fruits) {
    console.log(fruit);
}

// With index
fruits.forEach((fruit, index) => {
    console.log(`${index}: ${fruit}`);
});
▶ CONSOLE OUTPUT
apple
orange
3
["apple", "mango", "orange"]
1
true
[2, 3, 4]
0: apple
1: mango
2: orange

10 Array Methods

JavaScript arrays have powerful built-in methods for transformation and filtering. These are essential for modern JavaScript development.

JavaScript - Array Methods
const numbers = [1, 2, 3, 4, 5];

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

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

// FIND - get first matching element
const firstBig = numbers.find(n => n > 3);
console.log("First > 3:", firstBig);
// 4

// REDUCE - accumulate to single value
const sum = numbers.reduce((total, n) => total + n, 0);
console.log("Sum:", sum);
// 15

// SOME - check if any element passes
const hasLarge = numbers.some(n => n > 4);
console.log("Has number > 4:", hasLarge);
// true

// EVERY - check if all elements pass
const allPositive = numbers.every(n => n > 0);
console.log("All positive:", allPositive);
// true

// CHAINING methods together
const result = numbers
    .filter(n => n > 2)     // Keep > 2: [3, 4, 5]
    .map(n => n * 10);      // Multiply: [30, 40, 50]
console.log("Chained:", result);
▶ CONSOLE OUTPUT
Doubled: [2, 4, 6, 8, 10]
Even numbers: [2, 4]
First > 3: 4
Sum: 15
Has number > 4: true
All positive: true
Chained: [30, 40, 50]

11 Objects

Objects store data as key-value pairs. They're used to represent real-world entities and are fundamental to JavaScript.

JavaScript - Objects
// Creating objects
const person = {
    name: "Alice",
    age: 25,
    city: "NYC",
    isStudent: false,
    hobbies: ["coding", "reading"],
    
    // Method (function inside object)
    greet() {
        return `Hi, I'm ${this.name}!`;
    }
};

// Accessing properties
console.log(person.name);        // Dot notation: "Alice"
console.log(person["age"]);      // Bracket notation: 25
console.log(person.greet());     // "Hi, I'm Alice!"

// Modifying properties
person.age = 26;
person.email = "alice@email.com";  // Add new property

// Deleting properties
delete person.isStudent;

// Check if property exists
console.log("name" in person);  // true

// Get all keys/values
console.log(Object.keys(person));   // ["name", "age", "city", ...]
console.log(Object.values(person)); // ["Alice", 26, "NYC", ...]

// Loop through object
for (const key in person) {
    console.log(`${key}: ${person[key]}`);
}

// Nested objects
const company = {
    name: "TechCorp",
    address: {
        street: "123 Main St",
        city: "Boston"
    }
};
console.log(company.address.city);  // "Boston"
▶ CONSOLE OUTPUT
Alice
25
Hi, I'm Alice!
true
["name", "age", "city", "hobbies", "greet", "email"]
name: Alice
age: 26
city: NYC
hobbies: coding,reading
email: alice@email.com
Boston

12 DOM Manipulation

The DOM (Document Object Model) represents the HTML structure as objects. JavaScript can read and modify the DOM to make pages interactive.

DOM Selection Methods
getElementById
Single element
querySelector
CSS selector
querySelectorAll
Multiple elements
JavaScript - DOM
// SELECT elements
const title = document.getElementById("title");
const btn = document.querySelector(".btn");
const items = document.querySelectorAll(".item");

// MODIFY content
title.textContent = "New Title";          // Change text
title.innerHTML = "<em>Styled</em>";     // Change HTML

// MODIFY styles
title.style.color = "blue";
title.style.fontSize = "24px";

// ADD/REMOVE classes
title.classList.add("highlight");
title.classList.remove("old-class");
title.classList.toggle("active");  // Add if missing, remove if present

// MODIFY attributes
btn.setAttribute("disabled", "true");
btn.removeAttribute("disabled");

// CREATE new elements
const newDiv = document.createElement("div");
newDiv.textContent = "I am new!";
newDiv.classList.add("new-item");

// ADD to page
document.body.appendChild(newDiv);
// Or: parentElement.insertBefore(newDiv, existingElement);

// REMOVE element
// newDiv.remove();

9 Events

Events are things that happen on the page - clicks, key presses, form submissions. Event listeners let JavaScript respond to these actions.

JavaScript - Events
const button = document.querySelector("#myButton");
const input = document.querySelector("#myInput");

// CLICK event
button.addEventListener("click", () => {
    console.log("Button clicked!");
});

// CLICK with event object
button.addEventListener("click", (event) => {
    console.log("Clicked element:", event.target);
    event.preventDefault();  // Stop default action
});

// INPUT event - fires on every keystroke
input.addEventListener("input", (e) => {
    console.log("Current value:", e.target.value);
});

// KEYDOWN event
document.addEventListener("keydown", (e) => {
    if (e.key === "Enter") {
        console.log("Enter pressed!");
    }
});

// FORM SUBMIT
const form = document.querySelector("form");
form.addEventListener("submit", (e) => {
    e.preventDefault();  // Stop page reload
    const formData = new FormData(form);
    console.log("Form submitted!");
});

// MOUSE events
element.addEventListener("mouseenter", () => { /* hover in */ });
element.addEventListener("mouseleave", () => { /* hover out */ });

10 Async/Await (Advanced)

Asynchronous code handles operations that take time (API calls, file reading). async/await makes async code look synchronous and easier to read.

Async Flow
await
Wait for result
Result
Continue
JavaScript - Async/Await
// Simulated async function (like API call)
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// ASYNC function with AWAIT
async function fetchUserData() {
    console.log("Fetching data...");
    
    // 'await' pauses until promise resolves
    await delay(1000);  // Wait 1 second
    
    console.log("Data received!");
    return { name: "Alice", age: 25 };
}

// Call async function
fetchUserData().then(user => {
    console.log("User:", user);
});

// Using try/catch for errors
async function fetchWithErrorHandling() {
    try {
        const response = await fetch("https://api.example.com/data");
        
        if (!response.ok) {
            throw new Error("HTTP error!");
        }
        
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error("Error:", error.message);
    }
}

// Parallel async operations
async function fetchMultiple() {
    // Run both at same time, not sequentially
    const [user, posts] = await Promise.all([
        fetch("/api/user"),
        fetch("/api/posts")
    ]);
    console.log("Both loaded!");
}
▶ CONSOLE OUTPUT (with delays)
Fetching data...
(1 second passes)
Data received!
User: { name: "Alice", age: 25 }

11 Fetch API (Advanced)

The Fetch API makes HTTP requests to servers. It's used to get data from APIs, submit forms, and communicate with backends.

JavaScript - Fetch API
// GET request (fetch data)
async function getUsers() {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    const users = await response.json();
    console.log("Users:", users);
}

// POST request (send data)
async function createUser(userData) {
    const response = await fetch("https://api.example.com/users", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify(userData)
    });
    
    const newUser = await response.json();
    console.log("Created:", newUser);
}

// Usage
createUser({
    name: "Alice",
    email: "alice@example.com"
});

// Complete example with error handling
async function fetchData(url) {
    try {
        const response = await fetch(url);
        
        if (!response.ok) {
            throw new Error(`HTTP error: ${response.status}`);
        }
        
        return await response.json();
    } catch (error) {
        console.error("Fetch failed:", error);
        return null;
    }
}

12 Classes (ES6 OOP)

ES6 Classes provide a cleaner syntax for object-oriented programming in JavaScript. They're syntactic sugar over prototypes but make code much more readable.

JavaScript - Classes
// Class declaration
class Person {
    // Constructor - called when creating new instance
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    // Method
    greet() {
        console.log(`Hi, I'm ${this.name}!`);
    }
    
    // Getter
    get info() {
        return `${this.name}, ${this.age} years old`;
    }
    
    // Setter
    set birthday(date) {
        this._birthday = date;
    }
    
    // Static method - called on class, not instance
    static species() {
        return "Homo sapiens";
    }
}

// Create instances
const alice = new Person("Alice", 25);
const bob = new Person("Bob", 30);

alice.greet();                    // Hi, I'm Alice!
console.log(alice.info);           // Alice, 25 years old
console.log(Person.species());    // Homo sapiens

// INHERITANCE with extends
class Employee extends Person {
    constructor(name, age, role) {
        super(name, age);  // Call parent constructor
        this.role = role;
    }
    
    // Override parent method
    greet() {
        super.greet();     // Call parent method
        console.log(`I work as a ${this.role}`);
    }
    
    work() {
        console.log(`${this.name} is working...`);
    }
}

const dev = new Employee("Carol", 28, "Developer");
dev.greet();
dev.work();

// Private fields (ES2022+) - prefix with #
class BankAccount {
    #balance = 0;  // Private - can't access from outside
    
    deposit(amount) {
        this.#balance += amount;
    }
    
    getBalance() {
        return this.#balance;
    }
}

const account = new BankAccount();
account.deposit(100);
console.log(account.getBalance());  // 100
// console.log(account.#balance);   // ERROR! Private field
▶ CONSOLE OUTPUT
Hi, I'm Alice!
Alice, 25 years old
Homo sapiens
Hi, I'm Carol!
I work as a Developer
Carol is working...
100

13 Destructuring

Destructuring extracts values from arrays or properties from objects into distinct variables. It makes code cleaner and avoids repetitive access patterns.

JavaScript - Destructuring
// ARRAY DESTRUCTURING
const colors = ["red", "green", "blue"];

// Old way
const first = colors[0];
const second = colors[1];

// Destructuring way
const [red, green, blue] = colors;
console.log(red, green, blue);  // red green blue

// Skip elements
const [primary, , tertiary] = colors;
console.log(primary, tertiary);  // red blue

// Rest operator - collect remaining
const [head, ...rest] = [1, 2, 3, 4, 5];
console.log(head);  // 1
console.log(rest);  // [2, 3, 4, 5]

// OBJECT DESTRUCTURING
const person = {
    name: "Alice",
    age: 25,
    city: "NYC",
    job: "Developer"
};

// Extract specific properties
const { name, age } = person;
console.log(name, age);  // Alice 25

// Rename while destructuring
const { name: userName, city: location } = person;
console.log(userName, location);  // Alice NYC

// Default values
const { country = "USA" } = person;
console.log(country);  // USA (default used)

// Nested destructuring
const company = {
    name: "TechCorp",
    address: {
        street: "123 Main St",
        city: "Boston"
    }
};
const { address: { city: companyCity } } = company;
console.log(companyCity);  // Boston

// Function parameter destructuring
function printUser({ name, age, job = "Unknown" }) {
    console.log(`${name}, ${age}, ${job}`);
}
printUser(person);  // Alice, 25, Developer
▶ CONSOLE OUTPUT
red green blue
red blue
1
[2, 3, 4, 5]
Alice 25
Alice NYC
USA
Boston
Alice, 25, Developer

14 Spread & Rest Operators

The ... operator has two uses: Spread expands arrays/objects, Rest collects multiple elements. Same syntax, opposite behaviors.

Spread vs Rest
Spread ...
Expands items
vs
Rest ...
Collects items
JavaScript - Spread & Rest
// ========== SPREAD OPERATOR ==========

// Spread array elements
const nums1 = [1, 2, 3];
const nums2 = [4, 5, 6];
const combined = [...nums1, ...nums2];
console.log(combined);  // [1, 2, 3, 4, 5, 6]

// Copy array (shallow)
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original);  // [1, 2, 3] - unchanged!
console.log(copy);      // [1, 2, 3, 4]

// Spread in function calls
const numbers = [5, 10, 3, 8];
console.log(Math.max(...numbers));  // 10

// Spread objects
const defaults = { theme: "dark", lang: "en" };
const userPrefs = { theme: "light" };
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: "light", lang: "en" } - userPrefs overwrites

// Add properties while spreading
const person = { name: "Alice", age: 25 };
const updated = { ...person, age: 26, city: "NYC" };
console.log(updated);
// { name: "Alice", age: 26, city: "NYC" }

// ========== REST OPERATOR ==========

// Rest in function parameters
function sum(...nums) {
    return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4));  // 10

// Rest in destructuring
const [first, ...others] = [1, 2, 3, 4];
console.log(first);   // 1
console.log(others);  // [2, 3, 4]

const { name, ...restProps } = { name: "Bob", age: 30, city: "LA" };
console.log(name);       // Bob
console.log(restProps);  // { age: 30, city: "LA" }
▶ CONSOLE OUTPUT
[1, 2, 3, 4, 5, 6]
[1, 2, 3]
[1, 2, 3, 4]
10
{ theme: "light", lang: "en" }
{ name: "Alice", age: 26, city: "NYC" }
10
1
[2, 3, 4]
Bob
{ age: 30, city: "LA" }

15 Local Storage

Local Storage lets you store data in the browser that persists even after closing the tab. Perfect for user preferences, cached data, and offline functionality.

JavaScript - Local Storage
// STORE data (string only)
localStorage.setItem("username", "Alice");
localStorage.setItem("theme", "dark");

// RETRIEVE data
const username = localStorage.getItem("username");
console.log("Username:", username);  // Alice

// CHECK if key exists
if (localStorage.getItem("theme")) {
    console.log("Theme found!");
}

// STORE objects/arrays (must convert to JSON)
const user = {
    name: "Bob",
    age: 30,
    preferences: { notifications: true }
};

// Convert object to JSON string
localStorage.setItem("user", JSON.stringify(user));

// RETRIEVE and parse back to object
const storedUser = JSON.parse(localStorage.getItem("user"));
console.log(storedUser.name);  // Bob
console.log(storedUser.preferences.notifications);  // true

// STORE arrays
const todos = [
    { id: 1, text: "Learn JS", done: true },
    { id: 2, text: "Build project", done: false }
];
localStorage.setItem("todos", JSON.stringify(todos));

// REMOVE single item
localStorage.removeItem("theme");

// CLEAR all storage
// localStorage.clear();  // Removes everything!

// Get all keys
console.log("Keys in storage:");
for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    console.log(`  ${key}: ${localStorage.getItem(key)}`);
}

// SESSION STORAGE - same API, but clears on tab close
sessionStorage.setItem("temp", "This disappears when tab closes");
▶ CONSOLE OUTPUT
Username: Alice
Theme found!
Bob
true
Keys in storage:
  username: Alice
  user: {"name":"Bob","age":30,"preferences":{"notifications":true}}
  todos: [{"id":1,"text":"Learn JS","done":true},{"id":2,"text":"Build project","done":false}]

⚠️ Local Storage Limitations

• Only stores strings (use JSON for objects)
• ~5MB limit per domain
• Synchronous (can block UI for large data)
• Not secure for sensitive data (accessible via JS)

16 ES Modules

Modules let you split code across files and import/export functionality. This enables better organization, code reuse, and maintainability.

Module Import/Export Flow
module.js
export
main.js
import
JavaScript - utils.js (Module File)
// utils.js - Export multiple items

// Named exports
export const PI = 3.14159;

export function add(a, b) {
    return a + b;
}

export function multiply(a, b) {
    return a * b;
}

export class Calculator {
    add(a, b) { return a + b; }
    subtract(a, b) { return a - b; }
}

// Default export (one per file)
export default function greet(name) {
    return `Hello, ${name}!`;
}
JavaScript - main.js (Import File)
// main.js - Import from module

// Import default export
import greet from './utils.js';

// Import named exports
import { PI, add, multiply } from './utils.js';

// Import with alias
import { Calculator as Calc } from './utils.js';

// Import everything as namespace
import * as utils from './utils.js';

// Usage
console.log(greet("Alice"));   // Hello, Alice!
console.log(add(5, 3));          // 8
console.log(PI);                  // 3.14159

const calc = new Calc();
console.log(calc.add(10, 5));     // 15

// Using namespace import
console.log(utils.multiply(4, 5)); // 20
HTML - Enable Modules
<!-- Add type="module" to use ES modules in browser -->
<script type="module" src="main.js"></script>
▶ CONSOLE OUTPUT
Hello, Alice!
8
3.14159
15
20

💡 Module Best Practices

• One default export per file (main functionality)
• Use named exports for utilities and helpers
• Keep modules focused on single responsibility
• Use index.js to re-export from folders