Professional JavaScript Course

Master JavaScript in 10 Days

From first variable to async/await, closures to design patterns — a complete, structured path to professional-grade JavaScript.

10 Days · 50+ Topics
100+ Code Examples
Beginner → Advanced
Day 1Foundations
Day 01 / 10

Foundations of JavaScript

Understand what JavaScript is, how it runs in the browser and Node.js, and master the absolute basics: variables, data types, and operators.

What is JavaScript?

JavaScript is a high-level, interpreted, dynamically typed programming language. It is the only language that runs natively in web browsers, making it the backbone of interactive web experiences. Today, it also powers servers (Node.js), mobile apps (React Native), and desktop apps (Electron).

Interpreted

Code is executed line-by-line by the JavaScript engine (V8, SpiderMonkey) — no separate compile step needed.

Dynamic Typing

Variables can hold any type and change type at runtime. Types are resolved at execution, not at declaration.

Single-Threaded

JS runs on one thread but uses an event loop to handle async tasks without blocking.

Multi-Paradigm

Supports procedural, object-oriented, and functional programming styles.

Variables: var, let, const

Variables are named containers for storing data. JavaScript has three keywords for declaring them, each with different scoping and mutability rules.

KeywordScopeReassignableHoisted
varFunctionYesYes (undefined)
letBlockYesNo (TDZ)
constBlockNoNo (TDZ)
JavaScript
// var — function-scoped, avoid in modern JS
var name = "Alice";

// let — block-scoped, can be reassigned
let age = 25;
age = 26; // ✓ valid

// const — block-scoped, cannot be reassigned
const PI = 3.14159;
// PI = 3; → TypeError: Assignment to constant variable

// const with objects — the binding is const, not the content
const user = { name: "Bob" };
user.name = "Charlie"; // ✓ valid — mutation is allowed
💡
Best Practice

Use const by default. Switch to let only when you know the value needs to change. Avoid var entirely in modern JavaScript.

Data Types

JavaScript has 7 primitive types and one complex type (Object). Primitives are immutable and stored by value; objects are stored by reference.

JavaScript
// Primitives
const str       = "Hello";         // String
const num       = 42;              // Number
const bigint    = 9007199254740992n; // BigInt
const bool      = true;            // Boolean
const nothing   = null;            // Null
const undef     = undefined;       // Undefined
const sym       = Symbol("id");   // Symbol (unique)

// Complex type
const obj  = { x: 1, y: 2 };    // Object
const arr  = [1, 2, 3];          // Array (also an Object)
const func = () => {};            // Function (also an Object)

// typeof operator
console.log(typeof "hello");   // "string"
console.log(typeof 42);        // "number"
console.log(typeof null);      // "object" ← known JS quirk!
Operators

Operators perform operations on values. The critical distinction in JavaScript is between loose equality (==) and strict equality (===).

JavaScript
// Arithmetic
5 + 3    // 8
10 % 3   // 1 (modulo / remainder)
2 ** 8   // 256 (exponentiation)

// Comparison — ALWAYS use === and !==
5 === 5     // true  (strict: same value AND type)
5 == "5"    // true  (loose: coerces types — AVOID)
5 !== "5"   // true  (strict not-equal)

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

// Nullish coalescing (ES2020)
const val = null ?? "default"; // "default"

// Optional chaining (ES2020)
const city = user?.address?.city; // undefined (no error)
⚠️
Avoid Loose Equality

The == operator performs type coercion, which leads to surprising results like [] == false being true. Always use ===.

🎯

Day 1 Complete!

You know JavaScript's building blocks. Tomorrow: control flow, loops, and functions.

Day 02 / 10

Control Flow & Functions

Make decisions with conditionals, iterate with loops, and write reusable logic using the many forms of JavaScript functions.

Conditionals

Conditionals execute code based on whether a condition is truthy or falsy. JavaScript has 6 falsy values: false, 0, "", null, undefined, NaN.

JavaScript
// if / else if / else
const score = 85;

if (score >= 90) {
  console.log("A");
} else if (score >= 80) {
  console.log("B"); // ← runs this
} else {
  console.log("C or below");
}

// Ternary operator — concise one-liner
const status = score >= 60 ? "pass" : "fail";

// switch — best for many discrete cases
switch (status) {
  case "pass":
    console.log("Congratulations!");
    break;
  case "fail":
    console.log("Try again.");
    break;
  default:
    console.log("Unknown status");
}
Loops

Loops repeat code. Choose the right loop for the job: for when you know the count, while for condition-based repetition, and array methods (forEach, map) for cleaner iteration.

JavaScript
// Classic for loop
for (let i = 0; i < 5; i++) {
  console.log(i); // 0 1 2 3 4
}

// while loop
let count = 3;
while (count > 0) {
  console.log(count--); // 3 2 1
}

// for...of — iterates VALUES (arrays, strings)
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}

// for...in — iterates KEYS (objects)
const person = { name: "Alice", age: 30 };
for (const key in person) {
  console.log(key, person[key]); // name Alice, age 30
}

// break and continue
for (let i = 0; i < 10; i++) {
  if (i === 3) continue; // skip 3
  if (i === 6) break;    // stop at 6
  console.log(i);         // 0 1 2 4 5
}
Functions

Functions are first-class citizens in JavaScript — they can be stored in variables, passed as arguments, and returned from other functions. There are several ways to define them.

JavaScript
// 1. Function Declaration — hoisted (can be called before defined)
function greet(name) {
  return `Hello, ${name}!`;
}

// 2. Function Expression — not hoisted
const add = function(a, b) {
  return a + b;
};

// 3. Arrow Function — concise, no own 'this'
const multiply = (a, b) => a * b;      // implicit return
const square   = x => x ** 2;           // single param — no parens needed

// Default parameters (ES6)
const greetUser = (name = "World") => `Hello, ${name}!`;
greetUser();            // "Hello, World!"
greetUser("Alice");    // "Hello, Alice!"

// Rest parameters — gather remaining args into array
const sum = (...nums) => nums.reduce((a, b) => a + b, 0);
sum(1, 2, 3, 4); // 10
Scope & Hoisting

Scope defines where a variable is accessible. Hoisting is JavaScript's behavior of moving declarations to the top of their scope during compilation — but only for var and function declarations.

JavaScript
// Function declarations are hoisted
sayHi(); // "Hi!" — works even before definition
function sayHi() { console.log("Hi!"); }

// let/const have Temporal Dead Zone (TDZ)
// console.log(x); → ReferenceError
let x = 5;

// Block scope with let/const
{
  let inner = "only here";
  console.log(inner); // "only here"
}
// console.log(inner); → ReferenceError

// Closures — inner function remembers outer scope
function makeCounter() {
  let count = 0;
  return () => ++count;
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
ℹ️
Closures Are Powerful

Closures enable data privacy, function factories, and memoization. They're the foundation of many design patterns in JavaScript.

🔁

Day 2 Complete!

You can now control program flow and build reusable functions. Tomorrow: arrays, objects, and destructuring.

Day 03 / 10

Arrays, Objects & Destructuring

Master JavaScript's core data structures and learn modern ES6+ features like destructuring, spread, and rest that make working with data elegant.

Arrays — Creation & Access

Arrays are ordered, zero-indexed collections. They can hold any mix of types and grow or shrink dynamically.

JavaScript
const nums = [10, 20, 30, 40, 50];

// Access by index (0-based)
nums[0];       // 10
nums[4];       // 50
nums.at(-1);   // 50 ← ES2022 negative indexing

// Mutation methods
nums.push(60);      // add to end → [10,20,30,40,50,60]
nums.pop();         // remove from end
nums.unshift(0);   // add to start
nums.shift();       // remove from start
nums.splice(1, 2); // remove 2 elements at index 1

// Non-mutating
nums.slice(1, 3);   // [20, 30] — returns new array
nums.concat([70]); // new array with 70 appended
[...nums, 70];      // same with spread
Array Higher-Order Methods

These are the most important array methods in professional JavaScript. They take a callback function and return a new array or value without mutating the original.

JavaScript
const products = [
  { name: "Laptop",  price: 999, inStock: true  },
  { name: "Phone",   price: 699, inStock: false },
  { name: "Tablet",  price: 499, inStock: true  },
  { name: "Monitor", price: 399, inStock: true  },
];

// .map() — transform each element
const names = products.map(p => p.name);
// ["Laptop", "Phone", "Tablet", "Monitor"]

// .filter() — keep elements that pass a test
const available = products.filter(p => p.inStock);
// Laptop, Tablet, Monitor

// .reduce() — accumulate to a single value
const total = products.reduce((sum, p) => sum + p.price, 0);
// 2596

// .find() — first match
const cheapest = products.find(p => p.price < 500);
// { name: "Tablet", ... }

// .some() / .every()
products.some(p => p.price > 900);    // true
products.every(p => p.price > 100);  // true

// Chaining methods
const result = products
  .filter(p => p.inStock)
  .map(p => ({ ...p, discounted: p.price * 0.9 }))
  .sort((a, b) => a.price - b.price);
Objects

Objects store key-value pairs. Keys are strings (or Symbols); values can be anything. Objects are the backbone of JavaScript data modeling.

JavaScript
const user = {
  name: "Alice",
  age: 30,
  address: {
    city: "London",
    zip: "EC1A"
  },
  greet() { return `Hi, I'm ${this.name}`; }
};

// Property access
user.name;           // "Alice" (dot notation)
user["age"];         // 30    (bracket notation)

// Computed property names
const key = "status";
const obj = { [key]: "active" }; // { status: "active" }

// Useful Object methods
Object.keys(user);    // ["name", "age", "address", "greet"]
Object.values(user);  // ["Alice", 30, {...}, fn]
Object.entries(user); // [["name","Alice"], ["age",30], ...]
Object.assign({}, user, { age: 31 }); // shallow clone + override
Object.freeze(user); // makes object immutable
Destructuring, Spread & Rest

ES6 destructuring lets you unpack values from arrays or objects into variables concisely. Spread (...) copies items, rest (...) collects them.

JavaScript
// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4];
// first=1, second=2, rest=[3,4]

// Object destructuring
const { name, age, address: { city } } = user;
// name="Alice", age=30, city="London"

// Default values in destructuring
const { role = "guest" } = user; // "guest" (not in user)

// Renaming
const { name: userName } = user; // userName = "Alice"

// Spread — copy / merge
const cloned  = { ...user };
const updated = { ...user, age: 31 }; // immutable update pattern
const merged  = { ...defaults, ...overrides };

// Function destructuring in parameters
const display = ({ name, age = 18 }) =>
  console.log(`${name} is ${age}`);
📦

Day 3 Complete!

Arrays and objects mastered. Tomorrow: strings, numbers, and working with dates.

Day 04 / 10

Strings, Numbers & Dates

Work confidently with JavaScript's built-in String and Number methods, template literals, regular expressions, and the Date API.

String Methods

Strings are immutable in JavaScript. Every string method returns a new string. Template literals (backticks) enable multi-line strings and interpolation.

JavaScript
const str = "  Hello, JavaScript World!  ";

// Common methods
str.trim();                    // "Hello, JavaScript World!"
str.toLowerCase();             // "  hello, javascript world!  "
str.toUpperCase();             // "  HELLO, JAVASCRIPT WORLD!  "
str.includes("JavaScript");   // true
str.startsWith("  Hello");    // true
str.indexOf("World");          // 18
str.slice(2, 7);               // "Hello"
str.replace("JavaScript", "JS"); // replaces first match
str.replaceAll("l", "L");      // replaces all
str.split(", ");              // ["  Hello", "JavaScript World!  "]
str.padStart(30, "*");        // pads to length 30
str.repeat(2);                 // doubles the string

// Template literals
const name = "Alice";
const greeting = `
  Hello, ${name}!
  Today is ${new Date().toDateString()}.
  2 + 2 = ${2 + 2}
`;
Numbers & Math
JavaScript
// Number methods
const n = 3.14159;
n.toFixed(2);          // "3.14" (returns string)
n.toPrecision(4);       // "3.142"
Number("42");           // 42
parseInt("42px");       // 42
parseFloat("3.14em");  // 3.14
isNaN("hello");         // true
isFinite(Infinity);     // false

// 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();        // random float [0, 1)

// Random int between min and max (inclusive)
const randInt = (min, max) =>
  Math.floor(Math.random() * (max - min + 1)) + min;
⚠️
Floating Point Quirk

0.1 + 0.2 !== 0.3 in JavaScript (and most languages) due to IEEE 754 floating point. Use (0.1 + 0.2).toFixed(1) or multiply to integers for financial calculations.

Regular Expressions

Regular expressions (RegExp) are patterns for matching, searching, and replacing text.

JavaScript
// Create a regex
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
const phoneRegex = new RegExp('^\\d{10}$');

// test() — returns boolean
emailRegex.test("user@example.com"); // true

// match() — returns matches
"Hello World".match(/\b\w+\b/g); // ["Hello", "World"]

// replace() with regex
"foo bar baz".replace(/\s/g, "-"); // "foo-bar-baz"

// Named groups (ES2018)
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const { groups: { year, month, day } } = "2024-03-15".match(dateRegex);
🔤

Day 4 Complete!

String and number mastery achieved! Tomorrow: OOP with classes, prototypes, and inheritance.

Day 05 / 10

Object-Oriented Programming & Classes

Understand JavaScript's prototype-based inheritance, master ES6 classes, encapsulation, and design scalable object hierarchies.

Prototypes & Prototype Chain

Every JavaScript object has an internal link to another object called its prototype. When a property isn't found on an object, JS looks up the chain — this is called prototypal inheritance.

JavaScript
// All arrays inherit from Array.prototype
const arr = [1, 2, 3];
Object.getPrototypeOf(arr) === Array.prototype; // true

// Chain: arr → Array.prototype → Object.prototype → null

// Adding to prototype (don't do this for built-ins in production!)
Array.prototype.first = function() { return this[0]; };
[10, 20].first(); // 10

// hasOwnProperty — check own vs inherited
const obj = { a: 1 };
obj.hasOwnProperty("a");          // true
obj.hasOwnProperty("toString");   // false (inherited)
ES6 Classes

Classes are syntactic sugar over prototypes — they make OOP patterns cleaner and more readable. Under the hood, it's still prototype-based inheritance.

JavaScript
class Animal {
  // Private field (ES2022)
  #energy = 100;

  constructor(name, species) {
    this.name    = name;
    this.species = species;
  }

  // Instance method
  speak() {
    return `${this.name} makes a sound.`;
  }

  // Getter
  get energy() { return this.#energy; }

  // Setter
  set energy(val) {
    if (val < 0) throw new Error("Energy can't be negative");
    this.#energy = val;
  }

  // Static method — called on class, not instance
  static compare(a, b) {
    return a.name.localeCompare(b.name);
  }
}

// Inheritance with extends
class Dog extends Animal {
  constructor(name, breed) {
    super(name, "Canis lupus"); // call parent constructor
    this.breed = breed;
  }

  // Override parent method
  speak() {
    return `${this.name} barks!`;
  }
}

const rex = new Dog("Rex", "Labrador");
rex.speak();           // "Rex barks!"
rex instanceof Dog;    // true
rex instanceof Animal; // true
The this Keyword

this refers to the object executing the current function. Its value depends on how the function is called, not where it's defined.

JavaScript
// 'this' in methods → the object
const obj = {
  name: "Alice",
  greet() { return this.name; } // "Alice"
};

// Arrow functions inherit 'this' from surrounding scope
class Timer {
  constructor() { this.count = 0; }
  start() {
    // Arrow function captures 'this' from constructor context
    setInterval(() => this.count++, 1000);
  }
}

// Explicit binding: call, apply, bind
function introduce(greeting) {
  return `${greeting}, I'm ${this.name}`;
}

const person = { name: "Bob" };

introduce.call(person, "Hello");    // invoke with 'this'=person
introduce.apply(person, ["Hi"]);    // same but args as array
const bound = introduce.bind(person); // new function with fixed 'this'
🏗️

Day 5 Complete!

Halfway through! Tomorrow: the DOM, events, and building interactive UIs.

Day 06 / 10

The DOM & Events

The Document Object Model is JavaScript's interface to the browser. Learn to query elements, manipulate the DOM, and handle user interactions with events.

Selecting DOM Elements
JavaScript
// Modern query methods (returns live/static collections)
const btn    = document.querySelector("#submit-btn");
const inputs = document.querySelectorAll("input[type='text']");
const header = document.querySelector(".header h1");

// querySelectorAll returns a NodeList — convert to array for methods
const items = [...document.querySelectorAll(".item")];
items.forEach(item => console.log(item.textContent));

// Traversal
btn.parentElement;       // parent node
btn.children;            // HTMLCollection of children
btn.nextElementSibling;  // next sibling
btn.closest(".form");    // nearest ancestor matching selector
Manipulating the DOM
JavaScript
const el = document.querySelector("#box");

// Content
el.textContent = "Safe text";      // no HTML parsing
el.innerHTML   = "<b>Bold</b>";  // parsed as HTML (beware XSS)

// Attributes
el.setAttribute("data-id", "42");
el.getAttribute("data-id");   // "42"
el.removeAttribute("disabled");

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

// Styles
el.style.backgroundColor = "#ff6b35";
el.style.transform = "scale(1.1)";

// Creating & inserting elements
const newDiv = document.createElement("div");
newDiv.className = "card";
newDiv.textContent = "Hello!";
document.body.appendChild(newDiv);
document.body.insertBefore(newDiv, el);
el.insertAdjacentHTML("beforeend", "<span>+</span>");
Event Handling

Events are the core of interactive JavaScript. Use addEventListener instead of inline handlers for clean, maintainable code.

JavaScript
const btn = document.querySelector("#btn");

// Add event listener
btn.addEventListener("click", (event) => {
  event.preventDefault();  // stop default behavior
  event.stopPropagation(); // stop bubbling
  console.log(event.target);    // element clicked
  console.log(event.currentTarget); // listener's element
});

// Event delegation — handle children via parent
document.querySelector("#list")
  .addEventListener("click", (e) => {
    if (e.target.matches("li")) {
      console.log("Clicked:", e.target.textContent);
    }
  });

// Common events
el.addEventListener("mouseover", handler);
el.addEventListener("keydown", e => console.log(e.key));
el.addEventListener("submit", e => e.preventDefault());
el.addEventListener("input", e => console.log(e.target.value));

// Remove listener
btn.removeEventListener("click", handler);
🌐

Day 6 Complete!

You can now build interactive web pages! Tomorrow: async JS — promises, fetch, and async/await.

Day 07 / 10

Asynchronous JavaScript

JavaScript is single-threaded but handles async operations through the event loop. Master callbacks, Promises, async/await, and the Fetch API.

The Event Loop

JavaScript has a call stack (sync code), a task queue (macro-tasks like setTimeout), and a microtask queue (Promises). The event loop processes microtasks before macro-tasks.

JavaScript
console.log("1 — sync");

setTimeout(() => console.log("4 — macro-task"), 0);

Promise.resolve()
  .then(() => console.log("3 — microtask"));

console.log("2 — sync");

// Output: 1, 2, 3, 4
Promises

A Promise represents a value that may be available now, in the future, or never. It has three states: pending, fulfilled, or rejected.

JavaScript
// Creating a Promise
const fetchUser = (id) => new Promise((resolve, reject) => {
  setTimeout(() => {
    if (id > 0) {
      resolve({ id, name: "Alice" });
    } else {
      reject(new Error("Invalid ID"));
    }
  }, 1000);
});

// Consuming with .then/.catch/.finally
fetchUser(1)
  .then(user => console.log(user.name))   // "Alice"
  .catch(err => console.error(err))
  .finally(() => console.log("Done"));

// Promise combinators
Promise.all([fetchUser(1), fetchUser(2)])
  .then(([u1, u2]) => console.log(u1, u2));
// Fails if ANY promise rejects

Promise.allSettled([fetchUser(1), fetchUser(-1)])
  .then(results => results.forEach(r => console.log(r.status)));
// "fulfilled", "rejected" — never throws

Promise.race([fetchUser(1), fetchUser(2)]);
// resolves/rejects with whoever is first
Async / Await

async/await is syntactic sugar over Promises that makes async code read like synchronous code. An async function always returns a Promise.

JavaScript
// async function — implicitly returns a Promise
async function loadUserData(userId) {
  try {
    const user  = await fetchUser(userId);
    const posts = await fetchPosts(user.id);
    return { user, posts };
  } catch (error) {
    console.error("Failed:", error.message);
    throw error;
  }
}

// Parallel execution (don't await sequentially when independent!)
async function loadAll() {
  // BAD — sequential (2 seconds total)
  const a = await fetch1(); // 1s
  const b = await fetch2(); // 1s

  // GOOD — parallel (1 second total)
  const [a2, b2] = await Promise.all([fetch1(), fetch2()]);
}
Fetch API

The fetch function is the modern way to make HTTP requests in the browser. It returns a Promise.

JavaScript
// GET request
async function getUser(id) {
  const response = await fetch(`https://api.example.com/users/${id}`);

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  const data = await response.json();
  return data;
}

// POST request
async function createUser(userData) {
  const response = await fetch("https://api.example.com/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${token}`
    },
    body: JSON.stringify(userData)
  });

  return response.json();
}

Day 7 Complete!

Async JavaScript mastered! Tomorrow: ES6+ modules, error handling, and modern tooling.

Day 08 / 10

Modules, Error Handling & Tooling

Structure large applications with ES Modules, write bulletproof code with robust error handling, and understand the modern JavaScript toolchain.

ES Modules

Modules let you split code into separate files. Each module has its own scope — nothing is global unless explicitly exported.

JavaScript — math.js
// Named exports
export const add      = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const PI = 3.14159;

// Default export — one per file
export default function multiply(a, b) {
  return a * b;
}
JavaScript — app.js
// Import named exports
import { add, PI } from "./math.js";

// Import default export
import multiply from "./math.js";

// Import all as namespace
import * as Math2 from "./math.js";
Math2.add(1, 2);

// Dynamic import — loads only when needed
const { add: add2 } = await import("./math.js");
// Great for code splitting / lazy loading
Error Handling

Production code needs comprehensive error handling. Use try/catch/finally, create custom error types, and always handle Promise rejections.

JavaScript
// Custom Error classes
class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name  = "ValidationError";
    this.field = field;
  }
}

class NetworkError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name       = "NetworkError";
    this.statusCode = statusCode;
  }
}

// Catching specific error types
try {
  const data = await loadData();
  validate(data);
} catch (err) {
  if (err instanceof ValidationError) {
    showFieldError(err.field, err.message);
  } else if (err instanceof NetworkError) {
    showNetworkError(err.statusCode);
  } else {
    console.error("Unexpected error:", err);
    throw err; // re-throw unknown errors
  }
} finally {
  hideLoadingSpinner(); // always runs
}

// Unhandled Promise rejection handler
window.addEventListener("unhandledrejection", (e) => {
  console.error("Unhandled:", e.reason);
});
Modern JavaScript Toolchain
npm / pnpm / yarn

Package managers. Install libraries, manage dependencies, and run scripts defined in package.json.

Vite / Webpack

Build tools & bundlers. Bundle modules, transform code, enable HMR, and optimise for production.

Babel / SWC

Transpilers. Convert modern JS to browser-compatible versions. SWC is significantly faster (Rust-based).

ESLint / Prettier

Linting (catch errors & enforce rules) and formatting (consistent code style). Essential in any project.

TypeScript

A typed superset of JS that compiles to JavaScript. Adds static types, interfaces, and better tooling.

Jest / Vitest

Testing frameworks. Write unit tests, integration tests, and mocks to ensure code correctness.

🛠️

Day 8 Complete!

Your code is now production-ready. Tomorrow: functional programming patterns and advanced concepts.

Day 09 / 10

Functional Programming & Advanced Patterns

Embrace immutability, pure functions, and composition. Understand closures deeply, learn iterators and generators, and explore proxy and reflection.

Functional Programming Principles

Functional programming (FP) focuses on pure functions, immutability, and function composition. FP code is predictable and easy to test.

JavaScript
// Pure function — same input always = same output, no side effects
const double = x => x * 2; // ✓ pure

// Immutable updates (never mutate, always return new)
const addItem = (list, item) => [...list, item];
const updateUser = (user, updates) => ({ ...user, ...updates });

// Higher-order functions (functions that take/return functions)
const multiplyBy = factor => n => n * factor;
const triple     = multiplyBy(3);
const quadruple  = multiplyBy(4);

// Currying — transform f(a,b,c) into f(a)(b)(c)
const curry = (fn) => {
  return function curried(...args) {
    if (args.length >= fn.length) return fn(...args);
    return (...more) => curried(...args, ...more);
  };
};

const add = curry((a, b, c) => a + b + c);
add(1)(2)(3); // 6
add(1, 2)(3); // 6

// Composition — pipe functions left to right
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

const process = pipe(
  x => x * 2,
  x => x + 1,
  x => x ** 2
);
process(3); // ((3*2)+1)^2 = 49
Memoization & Closures (Advanced)
JavaScript
// Memoization — cache results of expensive calls
const memoize = (fn) => {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
};

const expensiveFib = memoize((n) =>
  n <= 1 ? n : expensiveFib(n-1) + expensiveFib(n-2)
);
Iterators & Generators

Generators are functions that can pause and resume execution using yield. They implement the iterator protocol.

JavaScript
// Generator function — denoted by function*
function* range(start, end, step = 1) {
  for (let i = start; i < end; i += step) {
    yield i;
  }
}

for (const n of range(0, 10, 2)) {
  console.log(n); // 0 2 4 6 8
}

// Infinite generator
function* ids() {
  let id = 1;
  while (true) yield id++;
}

const gen = ids();
gen.next().value; // 1
gen.next().value; // 2

// Async generators (ES2018)
async function* streamData() {
  for (const page of [1, 2, 3]) {
    yield await fetchPage(page);
  }
}

for await (const page of streamData()) {
  process(page);
}
WeakMap, WeakSet, Symbol, Proxy
JavaScript
// Symbol — unique, non-enumerable property keys
const id = Symbol("id");
const user = { [id]: 42, name: "Alice" };
Object.keys(user); // ["name"] — symbol not listed

// WeakMap — gc-friendly private data storage
const privateData = new WeakMap();
class Person {
  constructor(name) {
    privateData.set(this, { secret: "hidden" });
    this.name = name;
  }
}

// Proxy — intercept object operations
const handler = {
  get(target, key) {
    console.log(`Getting: ${String(key)}`);
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    if (typeof value !== "number") throw new TypeError("Numbers only!");
    return Reflect.set(target, key, value);
  }
};

const nums = new Proxy({}, handler);
nums.x = 10;   // ✓
nums.y = "hi"; // TypeError!
🧩

Day 9 Complete!

Advanced patterns unlocked! Final day tomorrow: design patterns, performance, and what's next.

Day 10 / 10

Design Patterns, Performance & What's Next

Cap your JavaScript journey with professional design patterns, browser performance techniques, security best practices, and a roadmap for continued mastery.

Design Patterns

Design patterns are reusable solutions to common software design problems. Here are the most relevant ones for JavaScript.

JavaScript — Singleton
// Singleton — only one instance ever created
class AppConfig {
  static #instance = null;

  constructor() {
    if (AppConfig.#instance) return AppConfig.#instance;
    this.theme = "dark";
    this.lang  = "en";
    AppConfig.#instance = this;
  }
}

const c1 = new AppConfig();
const c2 = new AppConfig();
c1 === c2; // true
JavaScript — Observer Pattern
// Observer — pub/sub event system
class EventEmitter {
  #events = {};

  on(event, listener) {
    (this.#events[event] ||= []).push(listener);
    return this;
  }

  off(event, listener) {
    this.#events[event] = this.#events[event]
      ?.filter(l => l !== listener);
    return this;
  }

  emit(event, ...args) {
    this.#events[event]?.forEach(l => l(...args));
  }

  once(event, listener) {
    const wrapper = (...args) => {
      listener(...args);
      this.off(event, wrapper);
    };
    return this.on(event, wrapper);
  }
}

const emitter = new EventEmitter();
emitter.on("data", payload => console.log(payload));
emitter.emit("data", { userId: 1 });
Performance Optimization
JavaScript
// Debounce — delay execution until after activity stops
const debounce = (fn, delay) => {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
};

// Throttle — execute at most once per interval
const throttle = (fn, limit) => {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      fn(...args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
};

// Usage
window.addEventListener("scroll", throttle(updateNav, 100));
searchInput.addEventListener("input", debounce(searchAPI, 300));

// requestAnimationFrame for smooth animations
function animate(timestamp) {
  // update position based on timestamp
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

// Virtual DOM concept — batch DOM updates
// (used by React, Vue under the hood)
const fragment = document.createDocumentFragment();
items.forEach(item => {
  const li = document.createElement("li");
  li.textContent = item;
  fragment.appendChild(li); // no DOM reflow
});
list.appendChild(fragment); // one reflow
Security Best Practices
XSS Prevention

Never use innerHTML with user data. Use textContent or sanitize with DOMPurify.

CSRF Protection

Use SameSite cookies, CSRF tokens, and validate origins with Origin headers.

Content Security Policy

Use CSP headers to prevent script injection attacks: Content-Security-Policy: default-src 'self'.

Input Validation

Validate ALL user input — both client-side (UX) and server-side (security). Never trust the client.

Your Next Steps
TypeScript

Add static types to JavaScript. Industry standard for large applications. 3–5 days to get productive.

React / Vue / Svelte

Component-based UI frameworks. React is the most in-demand. Build real projects immediately.

Node.js

Run JavaScript on the server. Build REST APIs, real-time apps, and CLIs. Pair with Express or Fastify.

Testing

Learn Jest or Vitest for unit tests. Playwright or Cypress for E2E. Testing = professional JS.

Data Structures & Algorithms

LeetCode in JS. Understanding DSA makes you a better engineer and clears technical interviews.

Build Real Projects

A todo app, a weather app, a full-stack clone. Real projects teach more than any tutorial.

🏆
Course Complete!
You've covered 10 days of professional JavaScript — from variables to design patterns. You now have the foundations to build anything.
NOW GO BUILD SOMETHING AMAZING