JavaScript Tutorial

JavaScript is the programming language of the web. It makes pages interactive - from form validation to real-time updates, animations, and full web applications (SPAs).

What is JavaScript?

  • Created by Brendan Eich in 1995 (originally called Mocha, then LiveScript).
  • Runs in the browser (client-side) AND on servers (Node.js).
  • Dynamically typed - no need to declare variable types.
  • Modern JavaScript uses the ECMAScript standard (ES6+ = ES2015+).
HTML
<!-- Inline JS -->
<script>
  alert("Hello, World!");
</script>

<!-- External JS (recommended) -->
<script src="app.js" defer></script>
► Try It Yourself

JavaScript Output

JavaScript
// Write to browser console (debug)
console.log("Hello");
console.warn("Warning!");
console.error("Error!");
console.table([{name:"Alice", age:25}]);

// Alert / Confirm / Prompt dialogs
alert("Hello World!");
const ok = confirm("Are you sure?");        // returns true/false
const name = prompt("Enter your name:", ""); // returns string

// Write into HTML
document.getElementById("demo").innerHTML = "<b>Hi!</b>";
document.getElementById("demo").textContent = "Safe text (no HTML)";

// Write to HTML document (only during loading)
document.write("Hello");  // overwrites if called after load
► Try It Yourself

Variables

JavaScript
// var - function-scoped, hoisted, re-declarable (avoid in modern JS)
var name = "Alice";

// let - block-scoped, not re-declarable, can be reassigned
let age = 25;
age = 26;

// const - block-scoped, cannot be reassigned (use for most variables)
const PI = 3.14159;
const user = { name: "Alice" };
user.name = "Bob"; // OK - object contents can change

// Rules
let myVar_1 = "valid";
// let 1var = "invalid"; // starts with number - error
// Reserved words (let, class, for) can't be variable names

// Destructuring assignment
const [a, b] = [1, 2];
const { x, y } = { x: 10, y: 20 };
► Try It Yourself

Data Types

TypeExampletypeof
String"Hello", 'World', `Template`"string"
Number42, 3.14, -7, Infinity, NaN"number"
BigInt9007199254740991n"bigint"
Booleantrue, false"boolean"
Undefined(variable declared but not assigned)"undefined"
Nullnull (intentional absence)"object" ??
SymbolSymbol("id")"symbol"
Object{}, [], null, new Date()"object"
Functionfunction(){}, ()=>{}"function"
JavaScript
// Type checking
typeof "hello"    // "string"
typeof 42         // "number"
typeof true       // "boolean"
typeof undefined  // "undefined"
typeof null       // "object" (historical bug!)
typeof []         // "object"
Array.isArray([]) // true (correct check)
null === null     // true

// Type conversion
Number("42")       // 42
Number("")         // 0
Number("abc")      // NaN
String(42)         // "42"
Boolean(0)         // false (falsy)
Boolean("")        // false (falsy)
Boolean("hello")   // true
► Try It Yourself

Operators

JavaScript
// Arithmetic
5 + 3    // 8     addition
5 - 3    // 2     subtraction
5 * 3    // 15    multiplication
10 / 3   // 3.33  division
10 % 3   // 1     modulus (remainder)
2 ** 8   // 256   exponentiation

// Assignment
let x = 10;
x += 5;  // x = 15
x -= 3;  // x = 12
x *= 2;  // x = 24
x /= 4;  // x = 6
x **= 2; // x = 36
x++;     // post-increment ? x = 37
++x;     // pre-increment

// Comparison (always use ===)
5 == "5"    // true  (loose - type coercion)
5 === "5"   // false (strict - no coercion) ?
5 !== "5"   // true  (strict not-equal)

// Logical
true && false  // false (AND)
true || false  // true  (OR)
!true          // false (NOT)

// Nullish coalescing ??
const name = null ?? "Guest"; // "Guest"
const age  = 0    ?? 18;      // 0 (0 is NOT null/undefined)

// Optional chaining ?.
const city = user?.address?.city; // undefined if user or address is null

// Ternary
const label = age >= 18 ? "Adult" : "Minor";
► Try It Yourself

Strings

JavaScript
const s = "Hello, World!";

s.length          // 13
s.toUpperCase()   // "HELLO, WORLD!"
s.toLowerCase()   // "hello, world!"
s.indexOf("o")    // 4 (first occurrence)
s.lastIndexOf("o")// 8
s.includes("World") // true
s.startsWith("He")  // true
s.endsWith("!")     // true
s.slice(7, 12)    // "World"
s.substring(7, 12)// "World"
s.replace("World", "JS")   // "Hello, JS!"
s.replaceAll("l", "L")     // "HeLLo, WorLd!"
s.split(", ")     // ["Hello", "World!"]
s.trim()          // remove leading/trailing spaces
s.padStart(20, "*")  // "***Hello, World!"
s.padEnd(20, "*")    // "Hello, World!***"
s.repeat(2)          // "Hello, World!Hello, World!"
s.charAt(0)          // "H"
s.charCodeAt(0)      // 72

// Template literals (backtick)
const name = "Alice";
const greet = `Hello, ${name}! You are ${25 + 1} years old.`;
const multiline = `
  Line 1
  Line 2
`;

// String.raw (no escape processing)
String.raw`C:\new\folder` // "C:\\new\\folder"
► Try It Yourself

Numbers

JavaScript
const n = 3.14159;
n.toFixed(2)          // "3.14"
n.toPrecision(4)      // "3.142"
n.toString()          // "3.14159"
n.toString(16)        // hex conversion

Number.isInteger(42)  // true
Number.isNaN(NaN)     // true
Number.isFinite(Infinity) // false
Number.parseInt("42px")   // 42
Number.parseFloat("3.14")  // 3.14
Number.MAX_SAFE_INTEGER    // 2^53 - 1

// Math object
Math.round(4.6)  // 5
Math.floor(4.9)  // 4
Math.ceil(4.1)   // 5
Math.abs(-5)     // 5
Math.max(1, 5, 3) // 5
Math.min(1, 5, 3) // 1
Math.sqrt(16)    // 4
Math.pow(2, 10)  // 1024
Math.random()    // 0-0.9999...
Math.trunc(4.9)  // 4 (integer part)
Math.sign(-5)    // -1

// Random integer between min and max (inclusive)
function randInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
► Try It Yourself

Arrays

JavaScript
const fruits = ["apple", "banana", "cherry"];

// Basic operations
fruits.length     // 3
fruits[0]         // "apple"
fruits.push("date")       // add to end ? 4
fruits.pop()              // remove from end ? "date"
fruits.unshift("avocado") // add to start
fruits.shift()            // remove from start

// Finding
fruits.indexOf("banana")  // 1
fruits.includes("cherry") // true
fruits.find(f => f.startsWith("b"))    // "banana"
fruits.findIndex(f => f.length > 5)   // 1

// Transforming (non-mutating - return new array)
fruits.map(f => f.toUpperCase())       // ["APPLE", "BANANA", ...]
fruits.filter(f => f.length > 5)      // ["banana", "cherry"]
fruits.reduce((acc, f) => acc + f, "")// "applebananacherry"
fruits.sort()                         // alphabetical sort
fruits.sort((a, b) => a.localeCompare(b))
fruits.reverse()
fruits.slice(1, 3)          // ["banana", "cherry"] (no mutation)
fruits.splice(1, 1)         // removes 1 element at index 1
fruits.concat(["elderberry"])
fruits.flat()               // flatten nested arrays
fruits.flatMap(f => [f, f.length])
fruits.every(f => f.length > 3)  // true if all match
fruits.some(f => f.startsWith("a")) // true if any match
fruits.join(", ")           // "apple, banana, cherry"

// Spread
const copy = [...fruits];
const merged = [...fruits, "elderberry", "fig"];

// Destructuring
const [first, second, ...rest] = fruits;

// Array.from
Array.from("hello")       // ["h","e","l","l","o"]
Array.from({length: 3}, (_,i) => i+1) // [1, 2, 3]
Array.of(1, 2, 3)         // [1, 2, 3]
► Try It Yourself

Objects

JavaScript
const user = {
  name: "Alice",
  age: 25,
  email: "alice@example.com",
  greet() { return `Hi, I'm ${this.name}`; },
  address: { city: "Mumbai", country: "India" }
};

// Access
user.name           // "Alice"
user["age"]         // 25
user.address.city   // "Mumbai"
user.greet()        // "Hi, I'm Alice"

// Modify
user.age = 26;
user.phone = "+91-999";
delete user.email;

// Check property existence
"name" in user       // true
user.hasOwnProperty("name") // true

// Iterate
Object.keys(user)    // ["name", "age", ...]
Object.values(user)  // ["Alice", 26, ...]
Object.entries(user) // [["name","Alice"], ...]
for (const [key, val] of Object.entries(user)) {
  console.log(`${key}: ${val}`);
}

// Spread / merge
const copy   = { ...user };
const merged = { ...user, role: "admin" };

// Destructuring
const { name, age, address: { city } } = user;
const { name: n = "Guest" } = {}; // default value

// Object.assign
const target = Object.assign({}, user, { role: "admin" });

// Object.freeze (immutable)
const config = Object.freeze({ debug: false });
// config.debug = true; // silently fails

// Computed property names
const key = "color";
const style = { [key]: "red" };  // { color: "red" }
► Try It Yourself

Conditionals

JavaScript
// if / else if / else
const score = 75;
if (score >= 90)      console.log("A");
else if (score >= 80) console.log("B");
else if (score >= 70) console.log("C");
else                  console.log("F");

// switch
const day = "Monday";
switch (day) {
  case "Saturday":
  case "Sunday":
    console.log("Weekend"); break;
  case "Monday":
    console.log("Back to work"); break;
  default:
    console.log("Weekday");
}

// Ternary operator
const status = score >= 50 ? "Pass" : "Fail";

// Short-circuit evaluation
const name = userInput || "Guest";   // fallback if falsy
const city = user && user.address && user.address.city;

// Nullish coalescing (only for null/undefined)
const theme = savedTheme ?? "light";
► Try It Yourself

Loops

JavaScript
// for loop
for (let i = 0; i < 5; i++) { console.log(i); }

// while loop
let i = 0;
while (i < 5) { console.log(i); i++; }

// do...while (runs at least once)
do { console.log(i); i++; } while (i < 5);

// for...of (iterate values - arrays, strings, Sets, Maps)
const nums = [10, 20, 30];
for (const n of nums) { console.log(n); }

// for...in (iterate keys of object)
const obj = { a: 1, b: 2 };
for (const key in obj) { console.log(key, obj[key]); }

// forEach (array method)
nums.forEach((n, index) => console.log(index, n));

// break and continue
for (let i = 0; i < 10; i++) {
  if (i === 5) break;       // exit loop
  if (i % 2 === 0) continue; // skip even numbers
  console.log(i);
}

// Labelled break (nested loops)
outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) break outer;
    console.log(i, j);
  }
}
► Try It Yourself

Functions

JavaScript
// Function declaration (hoisted)
function add(a, b) { return a + b; }

// Function expression (not hoisted)
const multiply = function(a, b) { return a * b; };

// Default parameters
function greet(name = "World") { return `Hello, ${name}!`; }

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

// Higher-order functions
function repeat(fn, n) { for (let i = 0; i < n; i++) fn(i); }
repeat(console.log, 3); // 0, 1, 2

// IIFE (Immediately Invoked Function Expression)
(function() { console.log("Runs immediately"); })();
(() => { console.log("Arrow IIFE"); })();

// Callback function
function fetchData(callback) {
  setTimeout(() => callback("data ready"), 1000);
}
► Try It Yourself

Arrow Functions

JavaScript
// Arrow function syntax
const add = (a, b) => a + b;
const square = n => n * n;        // single parameter, no parens needed
const greet = () => "Hello!";     // no parameters

// Multi-line body
const multiply = (a, b) => {
  const result = a * b;
  return result;
};

// Return object literal (wrap in parens)
const makeUser = name => ({ name, role: "user" });

// Arrow functions have NO own 'this'
// They inherit 'this' from enclosing scope
class Timer {
  start() {
    setInterval(() => {
      this.tick(); // 'this' refers to Timer instance ?
    }, 1000);
  }
  tick() { console.log("tick"); }
}
► Try It Yourself

DOM Manipulation

JavaScript
// Selecting elements
const el      = document.getElementById("myId");
const els     = document.getElementsByClassName("myClass");
const paras   = document.getElementsByTagName("p");
const btn     = document.querySelector(".btn"); // first match
const btns    = document.querySelectorAll(".btn"); // all matches

// Modifying content
el.innerHTML  = "<b>Bold text</b>";  // sets HTML (XSS risk with user input!)
el.textContent = "Safe text";           // safe - no HTML parsing
el.innerText   = "Visible text only";

// Attributes
el.getAttribute("href");
el.setAttribute("href", "https://example.com");
el.removeAttribute("disabled");
el.hasAttribute("required"); // true/false
el.dataset.userId;           // reads data-user-id attribute

// CSS Classes
el.classList.add("active");
el.classList.remove("hidden");
el.classList.toggle("open");
el.classList.contains("active"); // true/false

// Style
el.style.color = "red";
el.style.fontSize = "18px";
el.style.display = "none";

// Create & insert elements
const div = document.createElement("div");
div.textContent = "New element";
div.className = "card";
document.body.appendChild(div);           // add to end of body
document.body.insertBefore(div, nextEl);  // insert before element
el.prepend(div);   // add first child
el.after(div);     // insert after element
el.before(div);    // insert before element
el.remove();       // remove from DOM
el.replaceWith(newEl); // replace element

// Traversal
el.parentElement;
el.children;               // HTMLCollection of child elements
el.firstElementChild;
el.lastElementChild;
el.nextElementSibling;
el.previousElementSibling;
► Try It Yourself

Events

JavaScript
// addEventListener (preferred method)
btn.addEventListener("click", function(event) {
  console.log("Clicked!", event.target);
});

// Remove listener
function handler(e) { console.log(e); }
btn.addEventListener("click", handler);
btn.removeEventListener("click", handler);

// Event object
el.addEventListener("click", (e) => {
  e.preventDefault();      // stop default action (e.g. form submit, link)
  e.stopPropagation();     // stop event bubbling up DOM
  console.log(e.type);     // "click"
  console.log(e.target);   // element that was clicked
  console.log(e.clientX, e.clientY); // mouse coords
  console.log(e.key);      // keyboard key
});

// Common events
"click"       "dblclick"    "mouseenter"  "mouseleave"
"mouseover"   "mouseout"    "mousemove"   "mousedown"   "mouseup"
"keydown"     "keyup"       "keypress"
"submit"      "change"      "input"       "focus"       "blur"
"scroll"      "resize"      "load"        "DOMContentLoaded"
"touchstart"  "touchend"    "touchmove"

// Event delegation (efficient - add listener to parent)
document.addEventListener("click", (e) => {
  if (e.target.matches(".btn")) handleBtnClick(e.target);
});

// Form submit
form.addEventListener("submit", (e) => {
  e.preventDefault();
  const data = new FormData(form);
  console.log(data.get("email"));
});
► Try It Yourself

Promises & Async/Await

JavaScript
// Promise
const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Done!"), 1000);
  // setTimeout(() => reject(new Error("Fail")), 1000);
});

p.then(result => console.log(result))
 .catch(err => console.error(err))
 .finally(() => console.log("Always runs"));

// Promise.all (wait for multiple)
Promise.all([fetch(url1), fetch(url2)])
  .then(([r1, r2]) => console.log(r1, r2));

// Promise.race (first to finish)
Promise.race([p1, p2]).then(result => console.log(result));

// Promise.allSettled (all results, even rejected)
Promise.allSettled([p1, p2]).then(results => results.forEach(r => console.log(r.status)));

// async/await (syntactic sugar over Promises)
async function fetchUser(id) {
  try {
    const res  = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const data = await res.json();
    return data;
  } catch (err) {
    console.error("Failed:", err.message);
  }
}

// Parallel async
async function loadAll() {
  const [users, posts] = await Promise.all([
    fetchUsers(), fetchPosts()
  ]);
  return { users, posts };
}
► Try It Yourself

Fetch API

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

// POST request
async function createPost(post) {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(post)
  });
  return await res.json();
}

// PUT / PATCH / DELETE
await fetch(`/api/items/${id}`, { method: "DELETE" });

await fetch(`/api/items/${id}`, {
  method: "PATCH",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ field: "newValue" })
});

// With authentication header
await fetch("/api/protected", {
  headers: { "Authorization": `Bearer ${token}` }
});
► Try It Yourself

Classes & OOP

JavaScript
class Animal {
  // Private field
  #name;

  constructor(name, sound) {
    this.#name = name;
    this.sound = sound;
  }

  speak() { return `${this.#name} says ${this.sound}!`; }

  get name()       { return this.#name; }
  set name(value)  { this.#name = value; }

  static create(name, sound) { return new Animal(name, sound); }
}

// Inheritance
class Dog extends Animal {
  #breed;

  constructor(name, breed) {
    super(name, "Woof"); // call parent constructor
    this.#breed = breed;
  }

  fetch() { return `${this.name} fetches the ball!`; }

  speak() { // override parent method
    return super.speak() + " *tail wagging*";
  }
}

const dog = new Dog("Rex", "Labrador");
dog.speak();    // "Rex says Woof! *tail wagging*"
dog.fetch();    // "Rex fetches the ball!"
dog instanceof Dog;    // true
dog instanceof Animal; // true
► Try It Yourself

ES6+ Features

JavaScript - Modern Syntax
// ---- Destructuring ----
const [a, , b] = [1, 2, 3];           // a=1, b=3
const { x = 0, y = 0 } = point;       // with defaults
const { name: alias } = { name: "Alice" }; // rename

// ---- Spread & Rest ----
const arr = [...arr1, ...arr2];
const obj = { ...obj1, ...obj2 };
function fn(...args) { return args; }

// ---- Template Literals ----
const message = `Hello ${name}, you scored ${score * 2}!`;

// ---- Enhanced Object Literals ----
const name = "Alice", age = 25;
const user = { name, age, greet() { return `Hi ${this.name}`; } };

// ---- Symbol ----
const id = Symbol("id");
user[id] = 123; // non-enumerable, private

// ---- Map & Set ----
const map = new Map([["a", 1], ["b", 2]]);
map.set("c", 3); map.get("a");  // 1
map.has("b");    // true
map.size;        // 3
for (const [key, val] of map) { ... }

const set = new Set([1, 2, 2, 3]); // {1, 2, 3}
set.add(4); set.has(2);  // true
[...set];    // [1, 2, 3, 4]

// ---- WeakMap & WeakRef ----
const weakMap = new WeakMap(); // keys must be objects, no iteration

// ---- Generators ----
function* counter() {
  let i = 0;
  while (true) yield i++;
}
const gen = counter();
gen.next().value; // 0
gen.next().value; // 1

// ---- Proxy ----
const proxy = new Proxy(target, {
  get(obj, key) { return key in obj ? obj[key] : "default"; },
  set(obj, key, val) { obj[key] = val; return true; }
});

// ---- String methods (ES2021+) ----
"  hello  ".trimStart().trimEnd();
"ha".repeat(3);         // "hahaha"
"abc".at(-1);           // "c"
"abc".replaceAll("a", "A");

// ---- Array methods (ES2022+) ----
[1,[2,[3]]].flat(Infinity);   // [1,2,3]
[1,2,3].at(-1);         // 3
arr.findLast(x => x > 2); // last match
► Try It Yourself

Array Methods in Practice

Modern JavaScript relies heavily on array methods because they let you transform data without manual index loops.

JavaScript
const products = [
  { name: 'Keyboard', price: 2500, stock: 12 },
  { name: 'Mouse', price: 1200, stock: 0 },
  { name: 'Monitor', price: 18000, stock: 4 }
];

const inStock = products.filter(p => p.stock > 0);
const names = products.map(p => p.name);
const totalValue = products.reduce((sum, p) => sum + p.price * p.stock, 0);
const expensive = products.find(p => p.price > 10000);
const allAvailable = products.every(p => p.stock > 0);
const hasSoldOut = products.some(p => p.stock === 0);

JSON

JSON is the most common format for sending data between browsers, servers, and APIs. Students should understand the difference between a JavaScript object and a JSON string.

JavaScript
const user = { id: 1, name: 'Aisha', admin: false };

const jsonText = JSON.stringify(user);
console.log(jsonText); // '{"id":1,"name":"Aisha","admin":false}'

const parsedUser = JSON.parse(jsonText);
console.log(parsedUser.name); // 'Aisha'

localStorage.setItem('currentUser', JSON.stringify(user));
const savedUser = JSON.parse(localStorage.getItem('currentUser') || 'null');

Event Loop

JavaScript runs on a single main thread, but browsers and runtimes provide timers, network APIs, and task queues. The event loop decides when queued work can run.

JavaScript
console.log('A');

setTimeout(() => console.log('B - timer'), 0);
Promise.resolve().then(() => console.log('C - microtask'));
console.log('D');

// Output:
// A
// D
// C - microtask
// B - timer
Important Promise callbacks run before timer callbacks because microtasks are processed before the next macrotask.

Quick Quiz: What does === check compared to ==?