[Go to site: main page, start]

0% found this document useful (0 votes)
3 views76 pages

JavaScript Syllabus

The JavaScript Complete Mastery Syllabus is a structured learning path designed for learners from beginner to advanced levels, focusing on the MERN stack. It consists of 9 units, each requiring 400-500 hours of study and includes projects to reinforce understanding. The syllabus emphasizes self-directed learning, understanding JavaScript's unique features, and mastering the language through hands-on coding and exploration of underlying concepts.

Uploaded by

techstuff
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views76 pages

JavaScript Syllabus

The JavaScript Complete Mastery Syllabus is a structured learning path designed for learners from beginner to advanced levels, focusing on the MERN stack. It consists of 9 units, each requiring 400-500 hours of study and includes projects to reinforce understanding. The syllabus emphasizes self-directed learning, understanding JavaScript's unique features, and mastering the language through hands-on coding and exploration of underlying concepts.

Uploaded by

techstuff
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

JavaScript

Complete Mastery Syllabus


Beginner → Absolute Advanced · MERN Prep Track · Under the Hood Edition

9 Units 400–500h 9 Projects


Fully Structured Deep mastery estimate One per unit, no shortcuts

How To Use This Syllabus


This is not a tutorial. It is a map. Every topic tells you what to read, what to understand, and then what to
ask about what's happening underneath. You go find the answers yourself — that's the whole point.

The Rules
• Follow the topic order within each unit. The sequence is intentional — later topics
depend on earlier ones.
• For every topic: read first, experiment in the console/terminal, then tackle the 'Under the
Hood' section.
• Do not move to the next unit until you finish the project. The project exposes what you
think you understood but didn't.
• You write every line of code yourself. No copying. No AI-generated code.
• When stuck — bring your code here. We review it, we find the gaps, you go fix them.
• You can skip topics you already know solid. Just say so and we'll do a quick test to
confirm.

Reading Priority
• PRIMARY — [Link]: This is the best JS resource on the internet. Treat it like a
textbook.
• REFERENCE — MDN ([Link]): Use this when you want the exact,
authoritative definition of something.
• DEEP DIVE — ECMAScript Spec ([Link]/ecma262): The actual law of the language.
You will visit this for Under the Hood sections.
• ENGINE INTERNALS — V8 Blog ([Link]/blog): Written by the people who build the JS
engine. Required for true depth.
UNIT 1

JavaScript Foundations & Syntax


You know Java and C++. This unit is not about learning to code — it's about learning how
JS thinks. Spot the differences. They matter more than you think.
⏱ Time Estimate: 20–28 hours total (15–20h study + 6–8h project)

By the end of this unit you will:


• Understand how JS runs in the browser and in [Link]
• Know exactly why var/let/const exist and which to use when
• Understand JS dynamic typing and how it differs from Java's static typing
• Understand truthy/falsy — one of the most JS-specific concepts that will bite you everywhere
• Understand type coercion deeply — the == vs === story is much bigger than just 'use ==='
• Know the full set of operators including nullish coalescing and optional chaining
• Write clean control flow and understand for...of vs for...in (very different from Java)

Study Order — Do These In Sequence

What is JavaScript & How It Runs


1 Understand the environment before touching syntax

Variables — var, let, const


2 The first big JS-specific concept. Don't rush this.

Data Types & typeof


3 JS types are not Java types. There's null AND undefined. Both exist.

Type Coercion & Conversion


4 How JS secretly converts types — the source of half of all JS bugs

Operators
5 Mostly familiar, but == vs === and nullish coalescing are new

6 Truthy & Falsy


Not optional. This appears in every unit that follows.

Control Flow
7 Loops and conditionals. Mostly familiar, one new: for...of vs for...in

TOPIC 1 — What is JavaScript & How It Runs

What it is:
JS was originally built to run inside web browsers. Unlike Java where you compile to bytecode and the JVM
runs it, JS is interpreted (or JIT-compiled) by an engine built into the browser — V8 in Chrome, SpiderMonkey
in Firefox. Today it also runs on the server via [Link], which uses the V8 engine outside the browser.
Understanding this environment changes how you think about everything.
What to study:
• What JavaScript is and what problems it was built to solve
• How the browser loads and runs a JS file
• The <script> tag — where to put it, defer vs async attributes, and why position matters
• JS engines — V8, SpiderMonkey, JavaScriptCore — what they are
• What JIT (Just-In-Time) compilation means — JS is not purely interpreted
• [Link] — how it takes V8 out of the browser and runs JS on a server
• How to run JS: browser console, [Link] terminal, VS Code
• ECMAScript vs JavaScript — what the spec is and why it matters
• JS versions: ES5, ES6 (2015), ES2017, ES2020... what ES6 was and why it was a revolution

🔩 Under the Hood — Go here after the surface clicks.


– What V8 actually does — parsing your JS into an AST (Abstract Syntax Tree), then compiling hot
code with Turbofan
– What JIT compilation means — V8 starts interpreting with Ignition, then compiles frequently-run
code to machine code
– How the browser's rendering engine and JS engine share one thread — why slow JS freezes your
page
– Read: [Link]/blog — start with 'Launching Ignition and TurboFan'

📖 Read On: [Link]/intro · [Link]/devtools · MDN: What is JavaScript · [Link]/blog


(bookmark)

TOPIC 2 — Variables — var, let, const

What it is:
In Java, every variable has a type declared at compile time. In JS, variables have no declared type — they
hold whatever you put in them. But HOW you declare a variable (var vs let vs const) has massive implications
for scoping and hoisting. This is not just syntax — it determines how the JS engine allocates and looks up
memory.
What to study:
• var — function-scoped, hoisted to the top of its function, can be re-declared
• let — block-scoped (like Java), NOT hoisted in the same way as var
• const — block-scoped, must be initialized, cannot be reassigned (but object properties CAN be
mutated)
• Why var was the only option before ES6 and what problems it caused
• The Temporal Dead Zone (TDZ) — the zone where let/const exist but cannot be accessed
• Hoisting — what it means, how var is hoisted differently from let/const
• Variable naming rules and conventions in JS
• When to use const vs let — the rule: default to const, use let only when you need to reassign

🔩 Under the Hood — Go here after the surface clicks.


– Hoisting at the engine level — the creation phase vs execution phase of an execution context
– Why var lives on the Variable Object (VO) but let/const live in the TDZ until initialization
– Read the ECMAScript spec section on 'Runtime Semantics: BindingInitialization' —
[Link]/ecma262
– How V8 allocates variables — stack vs heap allocation

📖 Read On: [Link]/variables · [Link]/var · MDN: var · MDN: let · MDN: const

TOPIC 3 — Data Types & typeof

What it is:
JS has 8 data types. 7 are primitive (immutable, stored by value) and 1 is Object (stored by reference). This
split — primitives vs reference types — is the same concept you know from Java (int vs Integer) but in JS it
applies everywhere. The typeof operator tells you what type something is — but it has one famous bug that
has lived in the language since 1995.
What to study:
• The 7 primitive types: string, number, boolean, null, undefined, symbol, bigint
• The object type: objects, arrays, functions — all are 'object' under the hood
• typeof operator — what it returns for each type
• The famous typeof null === 'object' bug — why it exists and has never been fixed
• null vs undefined — they are not the same. null is intentional absence. undefined is 'not yet assigned'
• NaN — Not a Number. Why NaN is typeof 'number'. Why NaN !== NaN
• Infinity and -Infinity in JS numbers
• Primitives are immutable — what that actually means
• How strings behave like objects (you can call .length, .toUpperCase()) — wrapper objects
• BigInt — when to use it, what it solves with regular number precision
• Symbol — a unique, non-string key type. Brief intro here, deep dive in Unit 3

🔩 Under the Hood — Go here after the surface clicks.


– Why typeof null === 'object' — the original implementation used type tags in 32-bit values, and
null's tag was 000 which matched objects
– How JS numbers work — IEEE 754 double-precision floating point. Why 0.1 + 0.2 !== 0.3
– How primitive wrapper objects work — when you call 'hello'.toUpperCase(), JS temporarily boxes
the string into a String object
– Read: [Link]/primitives-methods for the boxing explanation

📖 Read On: [Link]/types · [Link]/primitives-methods · MDN: typeof · MDN: Data types

TOPIC 4 — Type Coercion & Type Conversion

What it is:
Type coercion is when JS automatically converts one type to another without you asking. It happens during
operations like addition, comparison, and logical evaluations. This is one of the most infamous features of JS
— it causes confusing bugs if you don't understand it, and it makes total sense once you do. Explicit
conversion is when YOU do it manually.
What to study:
• Implicit coercion — when JS converts types automatically during +, ==, if(), etc.
• The + operator with strings — '5' + 3 = '53' (concatenation beats addition)
• The - * / operators — these try to convert to numbers
• Explicit conversion: Number(), String(), Boolean()
• parseInt() and parseFloat() — how they parse strings to numbers
• Boolean conversion rules — what becomes true and what becomes false
• == (abstract equality) — the comparison algorithm with type coercion
• === (strict equality) — no coercion, same type required
• Why [] == false is true — walk through the actual coercion steps
• Why {} + [] = 0 in some contexts but '[object Object]' in others

🔩 Under the Hood — Go here after the surface clicks.


– The Abstract Equality Comparison Algorithm — read it in the spec: [Link]/ecma262 section
7.2.14
– The ToPrimitive operation — how JS converts objects to primitives (calls valueOf() and toString())
– The ToNumber operation — the algorithm that converts any value to a number
– Why NaN !== NaN — it's the only value in JS not equal to itself, defined by IEEE 754

📖 Read On: [Link]/type-conversions · [Link]/comparison · MDN: Equality comparisons ·


[Link]/operators

TOPIC 5 — Operators

What it is:
Most operators you know from Java. The interesting ones in JS are the ones that don't exist in Java: the
nullish coalescing operator (??) and optional chaining (?.). These were added to handle the reality that JS
code is full of null and undefined values, and crashing on them was a constant problem.
What to study:
• Arithmetic operators: +, -, *, /, %, ** (exponentiation — new in ES2016)
• Assignment operators: =, +=, -=, *=, /=, ??=, ||=, &&=
• Comparison operators: ==, ===, !=, !==, <, >, <=, >=
• Logical operators: && (AND), || (OR), ! (NOT)
• Short-circuit evaluation — && returns left if falsy, || returns left if truthy
• Nullish coalescing: ?? — returns right side only if left is null or undefined (not just falsy)
• Optional chaining: ?. — access nested properties without crashing if something is null
• typeof operator
• instanceof operator — checks prototype chain (you'll understand this fully in Unit 5)
• Comma operator — rarely used but exists
• Bitwise operators — brief, you know these from C++
• Operator precedence — when to use parentheses

🔩 Under the Hood — Go here after the surface clicks.


– How short-circuit evaluation works at the engine level — the logical operators don't return
true/false, they return one of their operands
– Why ?? was added separately from || — the problem with 0 and empty string being falsy
– Optional chaining (?.) under the hood — it generates a check for null/undefined before each
property access

📖 Read On: [Link]/operators · [Link]/logical-operators · [Link]/nullish-


coalescing-operator · [Link]/optional-chaining

TOPIC 6 — Truthy & Falsy

What it is:
In Java, only a boolean can be used in a condition. In JS, ANYTHING can be used in a condition. JS will
convert it to boolean. The values that become false are called 'falsy' — there are exactly 6 of them. Everything
else is 'truthy'. This concept appears in every single unit that follows. Do not skip this.
What to study:
• The 6 falsy values: false, 0, '' (empty string), null, undefined, NaN
• Everything else is truthy — including empty arrays [], empty objects {}, and the string '0'
• Why [] is truthy — this surprises most people coming from other languages
• Using truthy/falsy in if statements and ternary operators
• Double negation !! — converting any value to its boolean equivalent
• Boolean() function vs !! — both convert to boolean, same result
• Common patterns: if (user) {...} instead of if (user !== null && user !== undefined)
• Where truthy/falsy catches you out — the 0 problem: if (count) fails when count is legitimately 0

🔩 Under the Hood — Go here after the surface clicks.


– The ToBoolean abstract operation in the ECMAScript spec — the full algorithm for converting any
value to boolean
– Why the language designers chose these specific 6 falsy values

📖 Read On: [Link]/ifelse (section on truthy/falsy) · MDN: Truthy · MDN: Falsy

TOPIC 7 — Control Flow

What it is:
Control flow in JS is mostly the same as Java — if/else, switch, for, while. The main additions are for...of and
for...in, which are very different from each other and from Java's enhanced for loop. You also need to
understand labeled statements which exist but are rarely used.
What to study:
• if / else if / else — same as Java
• Ternary operator: condition ? valueIfTrue : valueIfFalse
• switch statement — same as Java, with the same fall-through behavior
• while loop and do...while loop
• for loop — same as Java
• for...in — iterates over object KEYS (property names). Not for arrays.
• for...of — iterates over iterable VALUES (arrays, strings, Maps, Sets). This is the one you'll use most.
• Why you should NOT use for...in on arrays — it iterates prototype properties too
• break and continue — same as Java
• Labeled statements — rare, but exist: outerLoop: for(...) { break outerLoop; }

🔩 Under the Hood — Go here after the surface clicks.


– How for...of works under the hood — it calls the [Link] method on the iterable (you'll
study this deeply in Unit 7)
– How for...in walks the prototype chain — why it picks up more than you expect on some objects
📖 Read On: [Link]/while-for · [Link]/switch · [Link]/ifelse · MDN: for...of · MDN:
for...in

🏗 UNIT PROJECT — Number Guessing Game (Terminal / Browser Console)


A classic project but with depth. The user thinks of a number 1–100. The program guesses it
using binary search. Then flip it — the user guesses and the program gives hot/cold feedback.
Build both modes.
Features to implement:
• Binary search guessing algorithm — computer guesses in max 7 tries
• User-guessing mode with attempts counter and hot/cold hints
• Input validation — handle non-numbers, out-of-range, repeated guesses
• Play again loop without page refresh
• Score tracking across multiple rounds
• Difficulty levels: Easy (1–50), Medium (1–100), Hard (1–500)

This project tests:


– Variables and proper use of const vs let
– All control flow: for, while, if/else, switch for difficulty
– Type coercion — user input is always a string, must be converted
– Truthy/falsy — for input validation
– Functions (preview of Unit 2 — write your first ones here)

UNIT 2

Functions — The Heart of JavaScript


In Java, functions are methods tied to classes. In JS, functions are first-class values. They
can be stored in variables, passed as arguments, returned from other functions. This
changes everything about how you write code.
⏱ Time Estimate: 40–55 hours total (30–40h study + 10–15h project)

By the end of this unit you will:


• Write functions every possible way: declarations, expressions, arrow functions
• Understand scope — global, function, block — and the scope chain
• Truly understand closures — not just 'what they are' but how they work in memory
• Pass functions as arguments and return functions from functions (higher-order functions)
• Use map, filter, reduce fluently — these are the most important array methods
• Understand what 'this' refers to in every possible context
• Know what call, apply, bind do and when to use them

Study Order — Do These In Sequence

Function Declarations & Expressions


1 The two main ways to define a function — they behave differently

Parameters, Arguments & Return


2 How data flows in and out of functions

Arrow Functions
3 The ES6 way — shorter syntax, different behavior for 'this'

Scope & the Scope Chain


4 Where variables live and how JS finds them

Closures
5 The most important concept in JS. Take your time here.

Higher-Order Functions & Callbacks


6 Functions that take and return functions

Array HOFs: map, filter, reduce


7 The holy trinity. You will use these every single day.

The 'this' Keyword


8 The most confusing thing in JS. Understand all 4 binding rules.

call, apply, bind


9 Manually controlling what 'this' refers to

IIFE & Advanced Patterns


10 Immediately invoked functions, pure functions, memoization
TOPIC 1 — Function Declarations vs Function Expressions

What it is:
There are two main ways to create a function in JS. A function declaration uses the 'function' keyword as a
statement. A function expression assigns a function to a variable. They look similar but behave very differently
due to hoisting.
What to study:
• Function declaration: function greet() {} — hoisted completely, can be called before it's defined
• Function expression: const greet = function() {} — NOT hoisted, treated like a variable
• Named function expressions — assigning a function with its own name to a variable
• Why function declarations are hoisted but function expressions are not
• Anonymous functions — functions with no name (common in function expressions)
• First-class functions — what it means that functions are values in JS
• Storing functions in variables, arrays, and object properties

🔩 Under the Hood — Go here after the surface clicks.


– Hoisting at the engine level — during the creation phase, function declarations are fully initialized
while var declarations are only declared (set to undefined)
– How function objects are stored in memory — functions are objects with a [[Call]] internal slot
– Read: [Link]/function-expressions — the section comparing declarations and expressions

📖 Read On: [Link]/function-basics · [Link]/function-expressions · MDN: Functions

TOPIC 2 — Parameters, Arguments, Rest & Spread

What it is:
Parameters are the variable names in the function definition. Arguments are the actual values you pass when
calling it. JS is very lenient here — you can pass more or fewer arguments than there are parameters and it
won't crash. This is different from Java's strict signature matching.
What to study:
• Parameters vs arguments — the distinction
• Passing more arguments than parameters — extra arguments are ignored
• Passing fewer arguments than parameters — missing ones are undefined
• Default parameters: function greet(name = 'World') — ES6 addition
• The arguments object — an array-like object available in regular functions (NOT arrow functions)
• Rest parameters: function sum(...nums) — collects all extra args into a real array
• Spread syntax: [Link](...arr) — expands an array into individual arguments
• The difference between rest (in function definition) and spread (in function call)
• Return values — a function without return returns undefined
• Multiple return values — JS doesn't support them, but you can return an array or object

🔩 Under the Hood — Go here after the surface clicks.


– The arguments object vs rest parameters — arguments is not a real array (no .map etc), rest gives
you a real Array
– How default parameters are evaluated — they run each time the function is called if needed
– Why you should prefer rest parameters over the arguments object in modern JS

📖 Read On: [Link]/function-basics · [Link]/rest-parameters-spread · MDN: Default


parameters

TOPIC 3 — Arrow Functions

What it is:
Arrow functions are a shorter way to write functions introduced in ES6. But they are NOT just shorthand —
they have a fundamentally different behavior around 'this'. Understanding when to use them and when NOT to
use them is critical. Most JS you read today will be full of arrow functions.
What to study:
• Basic syntax: const fn = (x) => x * 2
• Implicit return — single expression: no curly braces needed, value is returned automatically
• Explicit return — multi-line: needs curly braces and return keyword
• Parentheses rules — one param: can omit parens. Zero or multiple: parens required
• Returning an object literal — must wrap in parens: () => ({ key: value })
• Arrow functions do NOT have their own 'this' — they inherit from enclosing scope
• Arrow functions do NOT have arguments object
• Arrow functions cannot be used as constructors (cannot use new)
• Arrow functions do NOT have prototype property
• When NOT to use arrow functions: object methods, event handlers where you need 'this', constructors

🔩 Under the Hood — Go here after the surface clicks.


– How arrow functions capture 'this' — they close over the lexical 'this' of their enclosing context at
definition time
– How this is stored in the closure of an arrow function
– The internal [[ThisMode]] slot — regular functions have 'global' or 'strict', arrow functions have
'lexical'

📖 Read On: [Link]/arrow-functions-basics · [Link]/arrow-functions · MDN: Arrow


functions
TOPIC 4 — Scope & The Scope Chain

What it is:
Scope determines where a variable is accessible. JS has three kinds of scope: global, function, and block.
When JS looks for a variable, it starts in the current scope and walks up through outer scopes until it finds it —
this is the scope chain. If it reaches global scope and still can't find it, you get a ReferenceError.
What to study:
• Global scope — variables declared outside any function or block
• Function scope — var declared inside a function is only visible inside that function
• Block scope — let and const declared inside {} are only visible inside that block
• The scope chain — how JS walks up through nested scopes to find a variable
• Lexical scoping — scope is determined by where code is WRITTEN, not where it's called from
• Variable shadowing — a variable in inner scope hiding one in outer scope with the same name
• The global object — window in browsers, global in [Link], globalThis everywhere
• Strict mode — what 'use strict' does to scoping and undeclared variables

🔩 Under the Hood — Go here after the surface clicks.


– Execution contexts — every function call creates a new execution context with its own variable
environment
– The scope chain is built at function CREATION time (lexical scoping), not at call time
– How the engine walks the [[OuterEnv]] references to find variables
– Read: [Link]/closure — the sections on lexical environment

📖 Read On: [Link]/closure · MDN: Scope · [Link]/var

TOPIC 5 — Closures

What it is:
A closure is a function that remembers the variables from its outer scope even after that outer function has
finished executing. This sounds simple but has deep implications. Closures are the basis for data privacy,
module patterns, callbacks, and much of modern JS. This is the topic where most people think they
understand it and then discover they don't.
What to study:
• What a closure is — a function + the environment it was created in
• A simple closure example: a counter function that remembers its count
• How closures persist variables in memory even after the outer function returns
• Practical uses: data privacy (private variables), factory functions, partial application
• The famous closure-in-loop bug — var in a for loop, all callbacks share the same variable
• Fixing the closure-in-loop bug with let (block scope creates a new binding per iteration)
• Module pattern using closures — simulating private state before ES6 modules
• Closures and memory — closed-over variables cannot be garbage collected
• When closures cause memory leaks — holding references to DOM nodes or large objects

🔩 Under the Hood — Go here after the surface clicks.


– The Lexical Environment object — every execution context has one. It stores variables and a
reference to the outer Lexical Environment
– How closures work: when a function is created, it stores a [[Environment]] reference to the Lexical
Environment where it was created
– When the outer function returns, its execution context is destroyed — but the Lexical Environment
object stays alive as long as any closure references it
– This is what garbage collection is protecting against — the GC won't collect the Lexical
Environment while a closure holds a reference
– Read the Lexical Environment sections in: [Link]/closure

📖 Read On: [Link]/closure · MDN: Closures · [Link]/var

TOPIC 6 — Higher-Order Functions & Callbacks

What it is:
A higher-order function is a function that either takes a function as an argument or returns a function. This is
possible because functions are first-class values in JS. Callbacks are functions you pass to be called later —
this pattern is everywhere in JS, from DOM events to async operations.
What to study:
• First-class functions — what it means, why it matters
• Passing a function as an argument — the callback pattern
• Callbacks in the DOM: [Link]('click', myCallback)
• Callbacks in timers: setTimeout(myCallback, 1000)
• Callback hell — deeply nested callbacks that become unreadable
• Error-first callbacks — the [Link] pattern: callback(error, result)
• Returning functions from functions — creating function factories
• Functions that both take and return functions
• Synchronous vs asynchronous callbacks — understanding the difference

🔩 Under the Hood — Go here after the surface clicks.


– How callbacks enable asynchronous behavior — the function reference is stored and called later
by the event loop
– Function references in memory — passing a function passes a reference to the same function
object

📖 Read On: [Link]/callbacks · MDN: Callback function · [Link]/function-expressions


TOPIC 7 — Array HOFs: map, filter, reduce & More

What it is:
These are the most important methods you will use as a JS developer. map transforms every element. filter
picks elements that pass a test. reduce combines all elements into a single value. They are all higher-order
functions — they take a callback. Mastering these replaces most for loops you'd write.
What to study:
• forEach() — iterate over array, no return value. When to use vs for...of
• map() — create a new array by transforming every element. Returns new array, doesn't mutate
• filter() — create a new array with only elements that pass a test. Returns new array
• reduce() — combine all elements into one value using an accumulator
• reduce() for non-obvious uses: grouping, flattening, building objects from arrays
• find() — returns first element that passes a test (not an array, the actual element)
• findIndex() — returns index of first element that passes a test
• some() — returns true if ANY element passes the test
• every() — returns true if ALL elements pass the test
• flat() — flatten nested arrays
• flatMap() — map then flatten in one step
• Chaining: [Link](...).map(...).reduce(...) — the power of returning new arrays

🔩 Under the Hood — Go here after the surface clicks.


– These methods all call the callback with (element, index, array) — the third argument is often
forgotten
– map and filter create new arrays — they allocate new memory. For huge arrays, consider
performance
– reduce's accumulator — understanding the initial value parameter and what happens without it

📖 Read On: [Link]/array-methods · MDN: [Link] · MDN: [Link]

TOPIC 8 — The 'this' Keyword

What it is:
In Java, 'this' always refers to the current instance of the class. In JS, 'this' is dynamic — it depends on HOW
the function is called, not where it's defined (except for arrow functions). There are exactly 4 rules that
determine what 'this' is. Memorize these rules.
What to study:
• Rule 1 — Default binding: called as a plain function → this is global object (or undefined in strict mode)
• Rule 2 — Implicit binding: called as a method [Link]() → this is obj
• Rule 3 — Explicit binding: called with .call() or .apply() → this is what you pass
• Rule 4 — new binding: called with new → this is the newly created object
• Arrow functions: no rule applies — they inherit 'this' from the enclosing lexical scope
• The implicit binding bug — losing 'this' when you store a method in a variable
• Class methods and 'this' — the same rules apply
• Event listeners and 'this' — by default, this is the element the listener is attached to
• Why this is confusing — it's determined at runtime, not at definition time

🔩 Under the Hood — Go here after the surface clicks.


– The [[ThisValue]] slot in an execution context — how the engine stores and looks up 'this'
– How the Reference type works in the spec — the base value of a reference determines implicit
binding
– Read: [Link]/object-methods (the 'this' sections)

📖 Read On: [Link]/object-methods · MDN: this · [Link]/arrow-functions

TOPIC 9 — call, apply, bind

What it is:
These three methods let you manually control what 'this' refers to when calling a function. call and apply
invoke the function immediately with a specified this. bind returns a NEW function with 'this' permanently set
— it does not call immediately.
What to study:
• call(thisArg, arg1, arg2, ...) — call immediately, pass args as a list
• apply(thisArg, [arg1, arg2]) — call immediately, pass args as an array
• bind(thisArg, arg1, ...) — returns a new function with 'this' fixed. Does not call.
• Partial application with bind — pre-fill some arguments
• Common use: borrowing methods from one object to use on another
• Common use: fixing 'this' for callbacks that lose their context
• The difference: call/apply call now, bind returns a new function

🔩 Under the Hood — Go here after the surface clicks.


– How bind works under the hood — it creates a bound function exotic object with [[BoundThis]] and
[[BoundArguments]] internal slots
– The ECMAScript spec definition of [Link]
– How to implement your own version of bind using closures — a classic interview exercise (do this
yourself)
📖 Read On: [Link]/call-apply-decorators · [Link]/bind · MDN: [Link]

TOPIC 10 — IIFE, Pure Functions & Memoization

What it is:
An IIFE (Immediately Invoked Function Expression) is a function that runs as soon as it is defined. Pure
functions always return the same output for the same input and have no side effects. Memoization is a
technique to cache the result of expensive function calls.
What to study:
• IIFE syntax: (function() { ... })() or (() => { ... })()
• Why IIFEs were used — creating private scope before ES6 modules
• IIFEs for avoiding global variable pollution
• Pure functions — same input always produces same output, no side effects
• Impure functions — reading from/writing to external state, random numbers, current time
• Why pure functions are easier to test and reason about
• Side effects — what they are and why they need to be managed carefully
• Memoization — caching function results to avoid recomputing expensive operations
• Building a simple memoize function using closures and a Map

🔩 Under the Hood — Go here after the surface clicks.


– How IIFEs create their own lexical environment — they achieve encapsulation through the closure
mechanism
– Memoization and memory — the cache grows, use WeakMap for object keys to avoid memory
leaks

📖 Read On: [Link]/var · MDN: IIFE · [Link]/closure

🏗 UNIT PROJECT — Calculator with History (Terminal)


Build a calculator that supports chained operations and keeps a full history of every calculation.
Then add a feature where functions are passed as first-class values to perform operations.
Features to implement:
• Basic operations: add, subtract, multiply, divide, modulo, exponent
• Chaining: [Link](5).multiply(3).subtract(2) — method chaining pattern
• History: store every operation and result in an array
• printHistory() — display all previous calculations
• undo() — remove the last operation
• A 'run' function that accepts an array of operation functions and executes them in
sequence
• Memoized version of expensive calculations (e.g., factorial)

This project tests:


– All function types: declarations, expressions, arrow functions
– Closures — the history array lives in a closure
– Higher-order functions — passing operation functions
– map/filter on history (e.g., find all operations where result > 100)
– this keyword — in the chaining pattern
– Memoization pattern

UNIT 3

Objects & Arrays — Deep Dive


In JS, almost everything is an object. Arrays are objects. Functions are objects. Even null
was originally intended to be an object. Understanding how objects work in memory is the
key to understanding closures, prototypes, and the entire language.
⏱ Time Estimate: 35–47 hours total (25–35h study + 10–12h project)

By the end of this unit you will:


• Create and manipulate objects every way possible
• Understand pass-by-reference and why objects behave differently from primitives
• Use destructuring fluently — it's everywhere in modern JS and MERN code
• Master all array methods including the ones you haven't used before
• Know when to use Map and Set over plain objects and arrays
• Understand JSON — it's the universal data format of the web

Study Order — Do These In Sequence

Object Basics & Property Access


1 Creating objects, accessing and modifying properties

Object References & Copying


2 Why objects behave differently from primitives
Object Methods & Iteration
3 Walking through an object's properties

Destructuring
4 The modern way to pull data out of objects and arrays

Arrays — Core Methods


5 The mutating methods and non-mutating methods

Arrays — Functional Methods


6 map, filter, reduce revisited with more depth

Map & Set


7 When a plain object or array isn't enough

Strings — Full Coverage


8 Every method, every pattern

JSON
9 The data format of the web

TOPIC 1 — Object Basics & Property Access

What it is:
An object in JS is a collection of key-value pairs. Keys are strings (or Symbols). Values can be anything —
primitives, other objects, functions. Objects in JS are dynamic — you can add, change, and delete properties
at any time, unlike Java where a class defines the structure upfront.
What to study:
• Object literal syntax: const obj = { key: value, key2: value2 }
• Dot notation: [Link] — clean, but only works with valid identifier names
• Bracket notation: obj['property'] — works with any string, variables as keys, dynamic access
• Adding new properties at any time: [Link] = 'value'
• Updating properties: [Link] = 'newValue'
• Deleting properties: delete [Link]
• Shorthand property names (ES6): const name = 'Ali'; const obj = { name } instead of { name: name }
• Computed property names: const key = 'id'; const obj = { [key]: 123 }
• Checking if property exists: 'key' in obj vs [Link] !== undefined (they behave differently)
• hasOwnProperty() — check if property belongs to the object itself, not prototype
• [Link]() — the modern replacement for hasOwnProperty()
• Property shorthand in methods: { greet() {} } instead of { greet: function() {} }

🔩 Under the Hood — Go here after the surface clicks.


– How V8 stores object properties — 'hidden classes' (also called shapes or maps) for fast property
access
– Adding properties dynamically breaks hidden class optimization — V8 has to create a new hidden
class
– Property order in JS objects — integer keys are sorted, string keys maintain insertion order
(ES2015+)
– Read: [Link]/blog/fast-properties — how V8 optimizes object property access

📖 Read On: [Link]/object · MDN: Working with objects · [Link]/blog/fast-properties

TOPIC 2 — Object References & Copying

What it is:
Primitives are stored by value — assigning copies the value. Objects are stored by reference — assigning
copies the memory address. This means two variables can point to the same object, and changing it through
one variable affects the other. This is the source of many subtle bugs.
What to study:
• Primitive assignment copies the value — const a = 5; const b = a; — b has its own 5
• Object assignment copies the reference — const a = {}; const b = a; — both point to the same object
• Equality of objects — two objects with same properties are NOT equal: {} !== {}
• Shallow copy with spread: const copy = { ...original } — copies top-level properties
• Shallow copy with [Link](): [Link]({}, original)
• Why shallow copy is not enough for nested objects
• Deep copy with JSON: [Link]([Link](obj)) — works but has limitations (loses functions,
dates become strings)
• Deep copy with structuredClone() — modern, handles more types
• When shallow copy bites you — nested array or object still shared
• Freezing objects: [Link]() — makes object immutable (shallow freeze only)

🔩 Under the Hood — Go here after the surface clicks.


– How the JS heap works — objects live on the heap, variables hold references (memory
addresses) to heap locations
– Garbage collection and references — an object is collected only when NO references point to it
– structuredClone() — uses the HTML structured clone algorithm, supports more types than JSON

📖 Read On: [Link]/object-copy · MDN: structuredClone · MDN: [Link]


TOPIC 3 — Object Methods & Iteration

What it is:
[Link](), [Link](), and [Link]() are the three essential methods for getting data out of an
object. [Link]() goes the other direction. Combined with array methods, these let you transform
objects in powerful ways.
What to study:
• [Link](obj) — returns array of property names
• [Link](obj) — returns array of property values
• [Link](obj) — returns array of [key, value] pairs
• [Link](entries) — turns array of [key, value] pairs back into object
• for...in loop — iterates own AND inherited enumerable properties (be careful)
• Combining: [Link](obj).map(...) to transform an object
• Merging objects: [Link]() and spread { ...obj1, ...obj2 }
• [Link]() only returns own enumerable string keys — Symbol keys excluded
• Enumerable vs non-enumerable properties — brief intro (deep dive in Unit 5)

🔩 Under the Hood — Go here after the surface clicks.


– Own property vs inherited property — the difference, and why [Link]() only gives own
properties
– Property attributes: enumerable, configurable, writable — these determine how the property
behaves
– Full deep dive on property attributes in Unit 5

📖 Read On: [Link]/keys-values-entries · MDN: [Link] · MDN: [Link]

TOPIC 4 — Destructuring

What it is:
Destructuring lets you extract values from objects and arrays into named variables in a single line. It's one of
the ES6 features you'll use constantly in MERN code. React props are always destructured. API responses
are always destructured. Learn this cold.
What to study:
• Object destructuring: const { name, age } = person
• Renaming during destructuring: const { name: firstName } = person
• Default values in destructuring: const { name = 'Anonymous' } = person
• Array destructuring: const [first, second] = array
• Skipping elements: const [, , third] = array
• Rest in destructuring: const { name, ...rest } = obj — rest holds remaining properties
• Nested destructuring: const { address: { city } } = person
• Destructuring in function parameters: function greet({ name, age }) {}
• Swapping variables: [a, b] = [b, a]
• Destructuring return values: const [min, max] = getRange()
• Default values for nested: const { address: { city = 'Unknown' } = {} } = person

🔩 Under the Hood — Go here after the surface clicks.


– Destructuring is syntactic sugar — the engine converts it to a series of property accesses at parse
time
– Array destructuring uses the iteration protocol — it calls [Link] (you'll learn this in Unit 7)

📖 Read On: [Link]/destructuring-assignment · MDN: Destructuring assignment

TOPIC 5 — Arrays — Core Methods

What it is:
Arrays in JS are dynamic, untyped, and have a huge standard library. You need to know which methods
mutate the original array and which return a new one — this distinction matters for writing predictable code.
What to study:
• MUTATING — these change the original array:
• push() — add to end. pop() — remove from end
• unshift() — add to start. shift() — remove from start
• splice(start, deleteCount, ...items) — add/remove anywhere
• sort() — sorts IN PLACE. Warning: default sort is lexicographic, not numeric
• reverse() — reverses IN PLACE
• fill() — fill elements with a value
• NON-MUTATING — these return a new array:
• slice(start, end) — copy a portion of the array
• concat() — merge arrays. Same as spread: [...arr1, ...arr2]
• [Link]() — create array from iterables, array-like objects, or with a mapping function
• [Link]() — create array from arguments
• flat(depth) — flatten nested arrays
• flatMap() — map then flat(1)
• SEARCHING:
• indexOf() / lastIndexOf() — find by value using ===
• includes() — check if value exists
• find() — find first element by condition (returns element)
• findIndex() — find index of first element by condition
• findLast() / findLastIndex() — search from the end (ES2023)
• at() — access by index, supports negative: [Link](-1) is last element
🔩 Under the Hood — Go here after the surface clicks.
– Arrays in JS are NOT true arrays — they are objects with numeric string keys and a length
property
– How V8 optimizes arrays — dense arrays (all elements filled) use real C++ arrays internally.
Sparse arrays (holes) fall back to hash maps
– Why sort() is problematic without a comparator — the spec doesn't mandate a specific algorithm,
but V8 uses TimSort

📖 Read On: [Link]/array · [Link]/array-methods · MDN: Array

TOPIC 6 — Strings — Full Coverage

What it is:
Strings in JS are immutable primitive values. Every method that appears to modify a string actually returns a
new string. You'll use string methods constantly — parsing user input, manipulating data, building output.
What to study:
• String length: [Link]
• Accessing characters: str[0] and [Link](-1)
• Case: toUpperCase(), toLowerCase()
• Searching: indexOf(), lastIndexOf(), includes(), startsWith(), endsWith()
• Extracting: slice(start, end) — supports negative. substring(start, end) — does not
• Splitting: split(separator) — returns array
• Trimming: trim(), trimStart(), trimEnd()
• Replacing: replace(search, replacement), replaceAll()
• replace() with regex: [Link](/pattern/g, replacement)
• Padding: padStart(length, padStr), padEnd(length, padStr)
• Repeating: [Link](n)
• Template literals: `Hello ${name}` — backtick syntax
• Template literals with expressions: `${2 + 2}` = '4'
• Multi-line strings with template literals
• [Link]() — raw template strings, backslashes not processed

🔩 Under the Hood — Go here after the surface clicks.


– Strings are immutable — every method returns a new string. The original string in memory is
unchanged
– How JS stores strings internally in V8 — short strings use flat string representation, concatenation
uses 'cons strings' (a tree structure) for efficiency
– Why str[0] works — JS temporarily boxes the string into a String object to access the property
📖 Read On: [Link]/string · MDN: String

TOPIC 7 — Map & Set

What it is:
Map is like an object but keys can be ANY type (not just strings). Set is a collection of unique values. Both
have better performance characteristics than plain objects/arrays for certain operations and have cleaner
iteration APIs.
What to study:
• Map vs Object — when to use each. Map if: keys are non-strings, key insertion order matters explicitly,
frequent add/remove
• Creating a Map: new Map(), new Map([[key, val], ...])
• Map methods: set(key, val), get(key), has(key), delete(key), clear()
• [Link] — the size property (not .length)
• Iterating Maps: for...of with [Link](), [Link](), [Link]()
• Converting Map to array and back
• Set — stores unique values, any type
• Creating a Set: new Set(), new Set([1,2,3,2,1]) → {1,2,3}
• Set methods: add(val), has(val), delete(val), clear()
• Classic use: remove duplicates from array: [...new Set(arr)]
• Set operations — union, intersection, difference (must implement manually)
• WeakMap — like Map but keys must be objects, keys are weakly referenced (allows GC)
• WeakSet — like Set but values must be objects
• When to use WeakMap — storing metadata about objects without preventing GC

🔩 Under the Hood — Go here after the surface clicks.


– Map internally uses a hash table for O(1) average-case get/set operations
– WeakMap keys are weakly held — if the key object has no other references, it can be garbage
collected even if it's in the WeakMap
– This is the key difference from Map where the key reference PREVENTS garbage collection

📖 Read On: [Link]/map-set · [Link]/weakmap-weakset · MDN: Map · MDN: Set

TOPIC 8 — JSON

What it is:
JSON (JavaScript Object Notation) is the text format used to send data between servers and clients. Every
API you'll ever call returns JSON. Every request body you send will be JSON. You need to understand it
completely.
What to study:
• What JSON is — a text format derived from JS object syntax
• JSON vs JS object — key differences: keys must be double-quoted strings, no undefined, no functions,
no comments
• [Link](value) — convert JS value to JSON string
• [Link](string) — parse JSON string back to JS value
• [Link] with replacer and space arguments — filtering and formatting
• [Link] with reviver — transforming values while parsing
• toJSON() method on objects — customize how an object is stringified
• What gets lost in JSON serialization: functions, undefined, Symbol, Date (becomes string), circular
references
• Handling circular references — [Link] throws on circular refs
• Pretty printing: [Link](obj, null, 2)

🔩 Under the Hood — Go here after the surface clicks.


– [Link] walks the object and calls toJSON() if present, then serializes each value
– Circular reference detection — [Link] throws TypeError: Converting circular structure to
JSON
– The replacer function receives every key-value pair recursively — can be used to filter or
transform

📖 Read On: [Link]/json · MDN: [Link] · MDN: [Link]

🏗 UNIT PROJECT — Student Grade Manager


A full data management system for a class of students. No UI — pure JS data manipulation.
This forces you to use every object and array technique in real combination.
Features to implement:
• Store students as an array of objects: { id, name, grades: [{ subject, score }] }
• Add/remove students and grades
• Calculate GPA per student and class average
• Filter students by GPA range
• Sort students by name, GPA, or number of subjects
• Find top performer per subject
• Generate a summary report object using reduce
• Export data to JSON string and re-import it
• Find students at risk (GPA below threshold)
This project tests:
– Objects — creating, accessing, updating complex nested structures
– Arrays — every method: map, filter, reduce, find, sort
– Destructuring — pull data out cleanly
– Map — use a Map for O(1) student lookup by ID
– JSON — serialize and deserialize the entire dataset
– Closures — encapsulate the student database in a module-like pattern

UNIT 4

The Browser & The DOM


This is where JavaScript becomes visual. The browser gives you a JS API to read,
change, create, and delete everything on the page. Events let you respond to what the
user does. This unit bridges pure JS and front-end development.
⏱ Time Estimate: 37–51 hours total (25–35h study + 12–16h project)

By the end of this unit you will:


• Understand what the DOM is and how the browser builds it
• Select any element on a page using multiple methods
• Create, modify, move, and delete elements from JS
• Attach event listeners and handle user interactions
• Understand event bubbling and how event delegation works
• Use localStorage to persist data across page refreshes
• Work with timers: setTimeout and setInterval

Study Order — Do These In Sequence

How Browsers Work & The DOM


1 What the DOM actually is — not just a buzzword

Selecting Elements
2 Finding elements on the page from JS

Reading & Modifying Elements


3 Changing text, attributes, and CSS from JS
Creating & Removing Elements
4 Building and destroying DOM nodes from scratch

Events
5 Responding to user actions

Event Bubbling, Capturing & Delegation


6 How events travel through the DOM tree

Forms & User Input


7 Getting data from the user

Browser Storage & Timers


8 localStorage, sessionStorage, setTimeout, setInterval

TOPIC 1 — How Browsers Work & The DOM

What it is:
When a browser loads an HTML file, it parses the HTML and builds a tree of objects in memory. This tree is
the DOM — Document Object Model. Every HTML element becomes an object (a 'node') in the tree. JS can
then interact with these objects to read or change anything on the page.
What to study:
• The browser's rendering pipeline: HTML parsing → DOM tree → CSSOM → Render tree → Layout →
Paint
• What the DOM is — a tree of node objects representing the HTML document
• Node types: Element nodes (div, p, button), Text nodes, Comment nodes, Document node
• The document object — the entry point to the DOM from JS
• window vs document — window is the global object, document is the DOM root
• DOM vs HTML — the DOM is a live object tree, HTML is just text
• The DOM is live — JS changes to the DOM immediately update the page
• How to include JS in HTML: <script> tag placement (end of body, defer, async)
• DOMContentLoaded event — fires when HTML is parsed. load event — fires when everything including
images is loaded

🔩 Under the Hood — Go here after the surface clicks.


– The browser parsing pipeline — tokenization → token processing → building the node tree
– Render-blocking — how synchronous JS in <head> pauses HTML parsing (why we use
defer/async)
– The Critical Rendering Path — understanding this helps you write performant front-end code
– Reflow and repaint — changing layout properties triggers a full reflow (expensive). Changing only
colors triggers just a repaint
– Read: [Link]/web/fundamentals/performance/critical-rendering-path

📖 Read On: [Link]/dom-nodes · [Link]/browser-environment · MDN: Introduction to the


DOM

TOPIC 2 — Selecting Elements

What it is:
Before you can manipulate anything, you need to find it. JS gives you several methods to search the DOM.
querySelector is the most flexible and the one you'll use most.
What to study:
• [Link]('id') — fastest, returns single element
• [Link]('.class') — returns FIRST match, accepts any CSS selector
• [Link]('.class') — returns NodeList of ALL matches
• [Link]('class') — returns live HTMLCollection
• [Link]('div') — returns live HTMLCollection
• CSS selectors you can use in querySelector: #id, .class, tag, [attr], [Link], parent > child
• NodeList vs HTMLCollection — different types, NodeList from querySelectorAll is static, from
childNodes is live
• Traversing the DOM tree: parentElement, children, firstElementChild, lastElementChild
• nextElementSibling, previousElementSibling
• closest(selector) — walk UP the tree to find a matching ancestor
• matches(selector) — check if element matches a CSS selector

🔩 Under the Hood — Go here after the surface clicks.


– Live vs static collections — HTMLCollection is live (reflects current DOM). querySelectorAll returns
a static NodeList (snapshot)
– Why getElementById is faster — it uses a direct hash lookup in the document's ID map
– querySelectorAll uses the CSS Selector engine under the hood

📖 Read On: [Link]/searching-elements-dom · MDN: querySelector · MDN:


[Link]

TOPIC 3 — Reading & Modifying Elements


What it is:
Once you have a reference to an element, you can read and change everything about it: its text, HTML
content, attributes, CSS classes, and inline styles.
What to study:
• textContent — get/set plain text content. Safe — no HTML is parsed
• innerHTML — get/set HTML content. Dangerous with user input — XSS vulnerability
• innerText — like textContent but respects CSS visibility
• getAttribute(), setAttribute(), removeAttribute(), hasAttribute()
• [Link], [Link], [Link] — direct property access for common attributes
• dataset — accessing data-* attributes: [Link]
• [Link] — inline styles: [Link] = 'red'
• [Link](), [Link](), [Link](), [Link]()
• Why classList is better than manipulating className directly
• getComputedStyle(element) — get the actual computed CSS (includes stylesheets, not just inline)
• [Link]() — get element position and dimensions

🔩 Under the Hood — Go here after the surface clicks.


– Why innerHTML is dangerous — it parses the string as HTML and executes any <script> tags or
event handlers
– XSS (Cross-Site Scripting) — attacker injects HTML/JS through innerHTML. Always use
textContent for user-provided content
– Computed style vs inline style — computed style is the final result after all stylesheets and
specificity are applied

📖 Read On: [Link]/modifying-document · MDN: [Link] · MDN: classList

TOPIC 4 — Creating & Removing Elements

What it is:
You can build new HTML elements from scratch in JS, customize them, and insert them anywhere in the
DOM. You can also remove elements. This is how dynamic UIs are built — not by loading new pages, but by
modifying the existing DOM.
What to study:
• [Link]('tag') — create a new element in memory (not on page yet)
• [Link](child) — add child at the end of element
• [Link](...nodes) — add one or more nodes/strings at end
• [Link](...nodes) — add at start
• [Link](), [Link]() — insert before/after element (as sibling)
• [Link](position, html) — insert HTML at specific position
• [Link]() — remove element from DOM
• [Link](newElement) — replace element
• [Link](deep) — deep clone copies element and all children
• DocumentFragment — batch DOM operations in memory before inserting (performance)
• innerHTML = '' vs removeChild loop — clearing element's children

🔩 Under the Hood — Go here after the surface clicks.


– Why DocumentFragment matters — each DOM insertion triggers a reflow. Batching with
DocumentFragment inserts once
– The performance cost of DOM manipulation — each change to layout properties triggers browser
layout recalculation
– Virtual DOM (what React uses) — keep track of changes in memory and batch them. You'll study
this when you get to React

📖 Read On: [Link]/modifying-document · MDN: [Link] · MDN: DocumentFragment

TOPIC 5 — Events

What it is:
Events are things that happen in the browser — user clicks, keys pressed, pages loading, timers firing. JS lets
you attach listener functions that run when these events occur. This is the foundation of interactivity.
What to study:
• addEventListener(event, handler) — the correct way to attach events
• removeEventListener() — detaching listeners (must use same function reference)
• The Event object — passed to every handler: [Link], [Link], [Link]
• Mouse events: click, dblclick, mousedown, mouseup, mousemove, mouseenter, mouseleave
• Keyboard events: keydown, keyup — [Link], [Link], [Link], [Link]
• Form events: submit, change, input, focus, blur
• Window events: load, DOMContentLoaded, resize, scroll
• preventDefault() — stop default browser behavior (e.g., stop form from submitting)
• Inline HTML event handlers ( — understand them, but don't use them
• The old way: [Link] = fn — understand it, prefer addEventListener

🔩 Under the Hood — Go here after the surface clicks.


– How events are dispatched internally — the browser creates an Event object and dispatches it
through the DOM tree
– Why removeEventListener needs the same function reference — it matches by object identity, not
by code content

📖 Read On: [Link]/introduction-browser-events · [Link]/events · MDN:


[Link]
TOPIC 6 — Event Bubbling, Capturing & Delegation

What it is:
When an event fires on an element, it doesn't just stay there. It travels up through the DOM tree (bubbling)
from the target to the root. This behavior, once understood, enables a powerful pattern called event delegation
— attaching a single listener on a parent to handle events from many children.
What to study:
• Event propagation — 3 phases: capturing (down), target, bubbling (up)
• Bubbling — event travels from target element up to the document root
• Capturing — event travels from root down to target (rarely used)
• addEventListener third argument: true for capturing phase
• [Link] — the element that triggered the event
• [Link] — the element the listener is attached to
• stopPropagation() — stop the event from bubbling further up
• stopImmediatePropagation() — stop bubbling AND prevent other listeners on same element
• Event delegation — attach ONE listener on parent, check [Link] to handle children
• Why delegation is better for dynamic children — children added later are automatically handled
• Real example: click listener on a ul handles clicks on any li, even ones added later

🔩 Under the Hood — Go here after the surface clicks.


– How the browser determines the event path — it builds the full propagation path before
dispatching
– Why stopPropagation can cause bugs — it hides events from parent listeners that may also need
them
– Event delegation performance — 1 listener is cheaper than 1000 listeners on 1000 list items

📖 Read On: [Link]/bubbling-and-capturing · [Link]/event-delegation · MDN: Event


bubbling

TOPIC 7 — Forms & User Input

What it is:
Forms are how users send data. By default, submitting a form reloads the page — JS lets you intercept this,
validate the data, and handle it yourself. This is how every modern web app works.
What to study:
• Accessing form element: [Link]('form') or [Link]
• Accessing form fields by name: [Link]
• Getting input value: [Link] — always a string
• Checkboxes: [Link] — returns boolean
• Radio buttons: loop through and check .checked
• Select dropdowns: [Link] — current selected value
• preventDefault() on submit event — prevent page reload
• Input validation: check required fields, email format, length
• Input events: 'input' fires on every keystroke, 'change' fires when field loses focus
• focus() and blur() — programmatically focus/unfocus elements
• FormData object — collect all form values at once

🔩 Under the Hood — Go here after the surface clicks.


– Why form submit refreshes the page by default — it's a browser native behavior sending an HTTP
request
– The action and method attributes — where the form data goes if not intercepted

📖 Read On: [Link]/forms-controls · [Link]/form-elements · MDN: HTMLFormElement

TOPIC 8 — Browser Storage & Timers

What it is:
localStorage persists data between page sessions. sessionStorage persists for the current tab only.
setTimeout and setInterval let you run code after a delay or repeatedly. These are browser-specific APIs —
they don't exist in [Link].
What to study:
• [Link](key, value) — store a value
• [Link](key) — retrieve a value
• [Link](key), [Link]()
• localStorage only stores strings — must [Link] objects before saving
• [Link]() returns null if key doesn't exist — always check
• sessionStorage — same API as localStorage, clears when tab is closed
• localStorage vs sessionStorage vs cookies — when to use each
• setTimeout(fn, ms) — run fn once after ms milliseconds. Returns a timer ID
• clearTimeout(timerId) — cancel a pending timeout
• setInterval(fn, ms) — run fn every ms milliseconds. Returns a timer ID
• clearInterval(timerId) — cancel a repeating interval
• Why setTimeout(fn, 0) doesn't mean instant — it queues the callback in the event loop

🔩 Under the Hood — Go here after the surface clicks.


– setTimeout and setInterval are NOT part of the ECMAScript spec — they are browser/[Link]
APIs
– They work by adding callbacks to the task queue after the delay, not by pausing execution
– This is why setTimeout(fn, 0) still runs AFTER synchronous code — the current call stack must
clear first
– localStorage is stored on disk by the browser — it persists across browser restarts

📖 Read On: [Link]/localstorage · [Link]/settimeout-setinterval · MDN:


[Link]

🏗 UNIT PROJECT — Quiz App (Browser — HTML + CSS + JS)


Your first real browser project. A fully interactive quiz with multiple choice questions, a timer,
score tracking, and persistence. No frameworks — pure HTML + CSS + JS.
Features to implement:
• Load questions from a JS array of objects
• Display one question at a time with 4 options
• Click an option → immediately show correct/wrong with color highlight
• 60-second countdown timer per question — auto-advance when time runs out
• Next button to move to next question
• Track score and show progress: 'Question 3 of 10'
• End screen: final score, percentage, performance message
• Save high score to localStorage — persist across page refreshes
• Restart button — resets everything cleanly
• Shuffle questions and answers on each restart

This project tests:


– DOM selection and manipulation — building the UI dynamically
– Events — click, timer, keyboard shortcuts
– Event delegation — one listener handles all 4 option buttons
– localStorage — persist the high score
– setInterval and clearInterval — the countdown timer
– Objects and arrays — the question data structure
– Closures — timer function, state management

UNIT 5

OOP in JavaScript
JS is prototype-based, not class-based like Java. ES6 added class syntax but it's just
sugar over prototypes — the underlying mechanism is completely different from Java.
Understanding the prototype chain is essential for understanding the entire language.
⏱ Time Estimate: 40–55 hours total (30–40h study + 10–15h project)

By the end of this unit you will:


• Understand what a prototype is and how the prototype chain works
• Know the difference between constructor functions and ES6 classes (they compile to the
same thing)
• Write and use ES6 classes fluently — inheritance, static, private fields
• Understand property descriptors — enumerable, writable, configurable
• Use [Link], [Link], getters and setters correctly
• Know how instanceof actually works under the hood

Study Order — Do These In Sequence

Prototypes & the Prototype Chain


1 The foundation. Everything else in this unit depends on this.

Constructor Functions & new


2 The old way — important to understand before classes

ES6 Classes
3 The modern syntax — syntactic sugar over prototypes

Inheritance with extends & super


4 How to build class hierarchies

Static Methods & Properties


5 Belong to the class, not instances

Private Fields & Methods


6 Encapsulation the JS way

Property Descriptors
7 The metadata behind every object property

8 Getters & Setters


Computed properties and access control

[Link] & Prototype Manipulation


9 Direct prototype control

TOPIC 1 — Prototypes & The Prototype Chain

What it is:
Every object in JS has a hidden property called [[Prototype]]. This property points to another object — the
prototype. When you try to access a property that doesn't exist on the object, JS automatically looks at the
prototype, then the prototype's prototype, and so on up the chain until it reaches null. This chain is how
inheritance works in JS.
What to study:
• [[Prototype]] — the hidden link every object has to another object
• [Link](obj) — read the prototype
• [Link](obj, proto) — set the prototype (avoid in production code)
• __proto__ — the accessor property that exposes [[Prototype]] (deprecated, but you'll see it)
• The prototype chain — looking up properties by walking the chain
• null at the end — [Link]'s prototype is null, that's where the chain ends
• [Link] — the base prototype. Every object inherits from it unless you use [Link](null)
• hasOwnProperty() — check if property is own (not inherited). [Link]() is the modern version
• The for...in loop and the prototype chain — why it finds inherited properties
• Why [Link] exists — arrays inherit it through the chain

🔩 Under the Hood — Go here after the surface clicks.


– [[Prototype]] is an internal slot — a memory pointer to the prototype object
– Property lookup is a runtime operation — the engine walks the chain on every property access
that misses
– V8 caches property lookups using 'inline caches' — after the first lookup, subsequent accesses on
objects with the same hidden class are O(1)
– Read: [Link]/prototype-inheritance — especially the pictures showing the chain

📖 Read On: [Link]/prototype-inheritance · [Link]/native-prototypes · MDN: Inheritance


and the prototype chain

TOPIC 2 — Constructor Functions & The new Keyword

What it is:
Before ES6 classes, you created object blueprints with constructor functions. When you call a function with
'new', JS does 4 things automatically. Knowing these 4 steps is what makes 'new' understandable — and
helps you understand what classes compile to.
What to study:
• Constructor function convention — capitalize the name: function Person(name) {}
• The new keyword — what happens step by step:
• Step 1: Creates a new empty object {}
• Step 2: Sets the object's [[Prototype]] to [Link]
• Step 3: Calls the constructor with 'this' set to the new object
• Step 4: Returns the new object (unless constructor explicitly returns an object)
• [Link] — the object that new instances inherit from
• Adding methods to [Link] — shared across all instances (not duplicated per instance)
• instanceof — checks if [Link] is in the object's prototype chain
• What happens if you call a constructor without new — 'this' is global/undefined, disaster
• [Link] — inside a constructor, tells you if it was called with new

🔩 Under the Hood — Go here after the surface clicks.


– Implement your own version of the new keyword using [Link]() — this is a classic exercise
that proves you understand the mechanism
– function myNew(Constructor, ...args) { const obj = [Link]([Link]);
[Link](obj, args); return obj; }
– This is exactly what ES6 classes compile to (roughly)

📖 Read On: [Link]/constructor-new · MDN: new operator

TOPIC 3 — ES6 Classes

What it is:
ES6 introduced class syntax that looks like Java. But remember: it's syntactic sugar. Under the hood, it's still
prototypes and constructor functions. Classes are cleaner and more readable but understanding that they
compile to prototype-based code is crucial.
What to study:
• class declaration syntax: class Person { constructor() {} }
• class expression: const Person = class { ... }
• The constructor() method — called on new instantiation
• Instance methods — defined in the class body, added to prototype
• Instance properties — defined in constructor with [Link] = value
• Class fields (ES2022) — define properties directly in class body without constructor
• Classes are NOT hoisted like function declarations
• Classes are always in strict mode
• typeof ClassName === 'function' — classes are functions under the hood
• [Link] — where instance methods live
🔩 Under the Hood — Go here after the surface clicks.
– What the JavaScript engine actually does with class syntax — it's a function with methods added
to its prototype
– Class fields vs prototype methods — class fields are OWN properties (set on the instance),
prototype methods are SHARED
– Verify: inspect [Link] in the console and see the methods there

📖 Read On: [Link]/class · MDN: Classes

TOPIC 4 — Inheritance with extends & super

What it is:
The extends keyword sets up prototype chain inheritance between classes. super() calls the parent class
constructor. This gives you Java-like inheritance syntax while keeping the JS prototype chain underneath.
What to study:
• extends — class Dog extends Animal — sets up the prototype chain
• super() — must be called in child constructor BEFORE using 'this'
• Why super() must come first — the parent constructor creates the object, the child adds to it
• Calling parent methods: [Link]()
• Overriding methods — define a method with the same name in the child class
• instanceof with inheritance: new Dog() instanceof Animal — true, checks the full chain
• The prototype chain with classes: dog → [Link] → [Link] → [Link] → null
• Checking the exact type: [Link] === Dog
• Abstract class pattern — classes you don't instantiate directly (no native abstract in JS)
• Mixins — a pattern for sharing behavior across unrelated classes without inheritance

🔩 Under the Hood — Go here after the surface clicks.


– What extends actually does: sets [Link] = [Link]([Link]) and sets
[Link] = Child
– Why super() must come before 'this' — in derived classes, the object isn't created until super()
returns
– The [[HomeObject]] internal slot — how super method calls know which prototype to look in

📖 Read On: [Link]/class-inheritance · MDN: extends · MDN: super

TOPIC 5 — Static Methods & Properties


What it is:
Static members belong to the class itself, not to instances. You call them on the class: [Link]() not
[Link](). They're useful for utility functions, factory methods, and class-level state.
What to study:
• static method syntax: static create(data) { return new this(data) }
• Calling static methods: [Link]() — NOT on instances
• Static properties: static count = 0
• Using static for factory methods — alternative ways to construct instances
• Static methods are inherited — child class can call parent static methods
• Static vs instance — static is on the class object, instance methods are on the prototype
• [Link](), [Link]() — these are static methods on built-in classes
• [Link](), [Link]() — Math has only static methods (you never new Math())

🔩 Under the Hood — Go here after the surface clicks.


– Static methods and properties are own properties of the class function object itself
– They are NOT on [Link] — that's why instances can't access them
– Verify: [Link](ClassName) vs
[Link]([Link])

📖 Read On: [Link]/static-properties-methods · MDN: static

TOPIC 6 — Private Fields & Methods

What it is:
Private fields (using #) are a true privacy mechanism added in ES2022. Unlike closures-based privacy (the old
pattern), private fields are enforced by the engine — no workaround. This is the modern way to encapsulate
data in JS classes.
What to study:
• Private field syntax: #fieldName — declared at class body level
• Accessing private fields: this.#fieldName — only accessible inside the class
• Trying to access from outside throws: SyntaxError
• Private methods: #methodName() {}
• Private static fields and methods
• Why private fields are NOT the same as closure-based privacy
• Checking if object has a private field: #field in obj — works inside the class
• The old pattern: closure-based privacy using constructor function and closure
• WeakMap-based privacy — the pre-ES2022 pattern worth knowing

🔩 Under the Hood — Go here after the surface clicks.


– Private fields are stored in a separate slot on the object, not in the property table — they are not
discoverable through normal property lookup or reflection
– They are implemented as a brand check — the engine stores a unique brand per class, and
checks it before allowing access
– Private fields cannot be accessed even via Proxy — this is a deliberate security decision

📖 Read On: [Link]/private-protected-properties-methods · MDN: Private class features

TOPIC 7 — Property Descriptors

What it is:
Every property on an object has metadata attached to it — three boolean flags: writable (can the value be
changed?), enumerable (does it show up in for...in and [Link]()?), configurable (can the property be
deleted or its descriptor changed?). By default when you assign a property, all three are true. Built-in methods
often have them as false.
What to study:
• [Link](obj, 'prop') — read a property's descriptor
• [Link](obj) — get all descriptors
• [Link](obj, 'prop', descriptor) — define or modify with full control
• writable: false — value cannot be changed (silently fails outside strict mode, throws in strict)
• enumerable: false — property hidden from for...in and [Link]()
• configurable: false — property cannot be deleted, descriptor cannot be changed
• Data descriptor vs accessor descriptor — a property can have a value OR a getter/setter, not both
• [Link]() — makes all properties non-writable and non-configurable (shallow)
• [Link]() — makes all properties non-configurable but keeps them writable
• [Link](), [Link](), [Link]()
• [Link]() — no new properties can be added

🔩 Under the Hood — Go here after the surface clicks.


– Property descriptors are stored by the engine as internal metadata separate from the property
value
– In V8, non-enumerable, non-configurable, non-writable properties are stored differently for
optimization
– Read: [Link]/ecma262 — Property Attributes section for the formal definition

📖 Read On: [Link]/property-descriptors · MDN: [Link]


TOPIC 8 — Getters & Setters

What it is:
Getters and setters are special methods that act like properties. When you read [Link], it calls the
getter. When you assign [Link] = 'John Doe', it calls the setter. They let you compute values on the fly,
validate input, and run side effects on property access.
What to study:
• get keyword: get fullName() { return [Link] + ' ' + [Link] }
• set keyword: set age(value) { if (value < 0) throw new Error(); this._age = value }
• Using getters/setters in object literals
• Using getters/setters in classes
• Getter with no setter — read-only property
• Convention: _propertyName for the backing store
• [Link]() with get and set for accessor descriptors
• When to use getters: computed properties, lazy initialization, compatibility aliases

🔩 Under the Hood — Go here after the surface clicks.


– Getters and setters are accessor descriptors — the property descriptor has get and set fields
instead of value and writable
– Every property access on an object with a getter triggers a function call — don't put expensive
operations in getters
– Getter caching / lazy initialization pattern — compute once and cache: get value() { const v =
compute(); [Link](this, 'value', { value: v }); return v; }

📖 Read On: [Link]/property-accessors · MDN: getter · MDN: setter

TOPIC 9 — [Link] & Prototype Manipulation

What it is:
[Link](proto) creates a new object with a specified prototype. This gives you direct control over the
prototype chain without using classes or constructor functions. It's the most explicit way to set up prototype-
based inheritance.
What to study:
• [Link](proto) — create object with proto as its prototype
• [Link](null) — create object with NO prototype (no inherited methods — pure hash map)
• Using [Link] for inheritance without classes
• [Link] with property descriptors as second argument
• Setting up prototype chains manually — understanding what extends does
• [Link]() and [Link]()
• Why [Link]() is slow and should be avoided
• Checking prototype chain: [Link](obj)

🔩 Under the Hood — Go here after the surface clicks.


– [Link] is closer to the metal than class syntax — it directly sets [[Prototype]] without the
constructor overhead
– Why changing [[Prototype]] at runtime (setPrototypeOf) is slow — it invalidates V8's hidden class
optimization and inline caches for that object

📖 Read On: [Link]/prototype-methods · MDN: [Link]

🏗 UNIT PROJECT — Bank Account System


A fully featured bank account class hierarchy. No UI — pure OOP design. Focus on getting the
class design right — encapsulation, inheritance, private state.
Features to implement:
• Base Account class: private #balance, deposit(), withdraw(), getBalance()
• SavingsAccount extends Account: interest rate, calculateInterest(), applyInterest()
• CheckingAccount extends Account: overdraft limit, monthly fee
• Transaction history: private, recorded as objects { type, amount, date, balance }
• Static Bank class: manages multiple accounts, lookup by account number
• Transfer between accounts: [Link](fromAcc, toAcc, amount)
• Frozen account state: cannot deposit or withdraw
• toString() override — custom string representation of account
• getters for derived data: status, isOverdrawn, interestDue

This project tests:


– Prototypes — understand that class methods live on the prototype
– Private fields — #balance is truly private
– Inheritance — SavingsAccount and CheckingAccount extend Account
– super() — calling parent constructor
– Static methods — [Link]()
– Getters — computed properties
– Property descriptors — try making accountNumber non-writable

UNIT 6
Asynchronous JavaScript
This is the hardest unit. Async JS is the foundation of [Link], all web APIs, and the
MERN stack. The event loop, promises, and async/await are not optional knowledge —
they are the language. Take your time here.
⏱ Time Estimate: 55–75 hours total (40–55h study + 15–20h project)

By the end of this unit you will:


• Truly understand the Event Loop — not just 'there's a queue' but how it actually works
• Know the difference between the macrotask queue and the microtask queue
• Use Promises confidently including chaining and all Promise combinators
• Write async/await fluently and handle errors correctly
• Use the Fetch API to call real HTTP APIs
• Know how to handle all the edge cases: race conditions, timeout patterns, cancellation

Study Order — Do These In Sequence

JS is Single-Threaded — What Does That Mean?


1 The foundation. You must understand this before anything else in this unit.

The Call Stack


2 How JS tracks function execution

The Event Loop, Task Queue & Microtask Queue


3 The most important concept in async JS

Callbacks & Callback Hell


4 Where async started — and why we needed something better

Promises — Basics
5 The solution to callback hell

Promises — Combinators
6 Running multiple async operations

async / await
7 The clean syntax over promises
Error Handling in Async Code
8 try/catch with async, rejected promises, unhandled rejections

Fetch API & HTTP


9 Making real network requests

Advanced Patterns
10 Timeout, retry, cancellation, concurrency control

TOPIC 1 — JS is Single-Threaded — What Does That Mean?

What it is:
JavaScript has ONE thread of execution. It can only do one thing at a time. It cannot truly run two pieces of
code simultaneously. But it can WAIT for things (network requests, timers) without blocking — this is non-
blocking I/O. Understanding this distinction is the key to understanding all of async JS.
What to study:
• What a thread is — a sequence of instruction execution
• Single-threaded — one thread means one thing executing at a time
• Why single-threaded — JS was designed for the browser, shared state with one UI thread is simpler
• Blocking vs non-blocking — blocking halts the thread. Non-blocking delegates and continues.
• Synchronous code — runs line by line, each line blocks the next
• Asynchronous code — you start an operation, provide a callback, and continue running other code
• Why a slow synchronous operation (like a while loop) freezes the browser entirely
• Concurrency vs parallelism — JS achieves concurrency (interleaving) not parallelism (simultaneous)

🔩 Under the Hood — Go here after the surface clicks.


– Web Workers — a way to run JS on a SEPARATE thread. Not the main thread. Limited API (no
DOM access)
– [Link] and libuv — Node uses a thread pool for file I/O, DNS lookups, etc. but your JS code is
still single-threaded
– The actual I/O operations are delegated to the OS, which uses mechanisms like epoll (Linux) or
kqueue (macOS)

📖 Read On: [Link]/event-loop · MDN: Concurrency model · [Link] (visual event


loop)

TOPIC 2 — The Call Stack


What it is:
The call stack is how JS tracks which function is currently running and what called it. When you call a function,
it's pushed onto the stack. When it returns, it's popped off. The stack is LIFO — Last In, First Out. If the stack
gets too deep (infinite recursion), you get a 'Maximum call stack size exceeded' error.
What to study:
• What a stack is — LIFO data structure
• How function calls push frames onto the stack
• How return pops frames off the stack
• The global execution context — always at the bottom of the stack
• Stack overflow — infinite recursion fills the stack until the engine throws
• Reading a stack trace — understanding the error output
• Tail call optimization — ES6 theoretically supports it, V8 support is limited

🔩 Under the Hood — Go here after the surface clicks.


– Each stack frame is an execution context — contains the function's local variables, parameters,
and the this value
– Stack frames are allocated in memory (often on the native stack or a simulated stack)
– Stack overflow at the engine level — the engine has a hard limit on call stack depth
– Use the browser DevTools Sources tab to see the actual call stack at any breakpoint

📖 Read On: [Link]/recursion (call stack section) · MDN: Call stack

TOPIC 3 — The Event Loop, Task Queue & Microtask Queue

What it is:
This is the mechanism that makes JS asynchronous without being multi-threaded. The event loop
continuously checks: is the call stack empty? If yes, take the next task from the queue and push it onto the
stack. There are two queues: the macrotask queue (tasks) and the microtask queue (microtasks — which run
first).
What to study:
• The event loop — a loop that checks if the call stack is empty, then processes queued callbacks
• The macrotask queue — where setTimeout, setInterval, I/O callbacks, and UI events go
• The microtask queue — where Promise .then() callbacks and queueMicrotask() callbacks go
• CRITICAL: microtasks run after the current task but BEFORE the next macrotask
• Processing order: synchronous code → microtasks → macrotask → microtasks → macrotask...
• Why [Link]().then() runs before setTimeout(fn, 0)
• MutationObserver callbacks — also microtasks
• queueMicrotask() — manually queue a microtask
• Why starving the event loop is dangerous — infinite microtasks prevent the next macrotask from ever
running
• Visualize this: use [Link] and watch the event loop in action
🔩 Under the Hood — Go here after the surface clicks.
– The HTML spec defines the event loop — not the ECMAScript spec. The browser implements it.
– [Link] has its own event loop (implemented by libuv) with phases: timers, I/O callbacks, idle, poll,
check, close. More phases than browser.
– The microtask checkpoint — runs after EVERY task, not just when the call stack is clear
– Read: [Link]/multipage/[Link]#event-loops
– Read: [Link]/2015/tasks-microtasks-queues-and-schedules/ — the best article on this

📖 Read On: [Link]/event-loop · [Link]/2015/tasks-microtasks-queues-and-


schedules · [Link]

TOPIC 4 — Callbacks & Callback Hell

What it is:
Before Promises, async code was handled with callbacks. You pass a function to be called when the async
operation completes. This worked but led to deeply nested code when operations depended on each other —
called 'callback hell' or the 'pyramid of doom'.
What to study:
• Callback pattern — passing a function to be called later
• Synchronous callbacks — forEach, map (called immediately, not async)
• Asynchronous callbacks — setTimeout, event listeners, HTTP requests
• Error-first callbacks — [Link] convention: first argument is error or null
• Callback hell — nested callbacks for sequential async operations
• Problems: hard to read, hard to error handle, hard to compose
• Why promises were invented — to solve callback hell

🔩 Under the Hood — Go here after the surface clicks.


– When an async operation completes (timer fires, network responds), the browser/[Link] places
the callback into the macrotask queue
– The callback doesn't run immediately — it waits for the call stack to be empty

📖 Read On: [Link]/callbacks · [Link] (read this)

TOPIC 5 — Promises — Basics

What it is:
A Promise is an object representing the eventual completion or failure of an async operation. It has three
states: pending, fulfilled (resolved with a value), or rejected (failed with a reason). Promises let you chain
async operations and handle errors in one place.
What to study:
• Creating a Promise: new Promise((resolve, reject) => { ... })
• resolve(value) — fulfill the promise with a value
• reject(reason) — reject the promise with an error
• Promise states: pending → fulfilled or pending → rejected (states are final once set)
• .then(onFulfilled) — callback when promise resolves
• .catch(onRejected) — callback when promise rejects
• .finally(fn) — always runs, resolved or rejected
• Promise chaining — .then() returns a new Promise, enabling chaining
• Returning values in .then() — the value becomes the resolved value of the next promise
• Returning a Promise in .then() — the chain waits for it
• Error propagation — a rejection skips .then() handlers until it hits a .catch()
• [Link](value) and [Link](reason) — create immediately settled promises

🔩 Under the Hood — Go here after the surface clicks.


– Promise callbacks (.then) are microtasks — they go into the microtask queue, not the macrotask
queue
– This is why Promises are always asynchronous even if they resolve synchronously
– A Promise is an object with internal [[PromiseState]] and [[PromiseResult]] slots
– Implement a simple Promise from scratch — this is the best way to understand it (search: 'Build
your own Promise')

📖 Read On: [Link]/promise-basics · [Link]/promise-chaining · MDN: Promise

TOPIC 6 — Promises — Combinators

What it is:
Promise combinators let you manage multiple async operations at once. [Link]() is the one you'll use
most — it runs multiple promises in parallel and waits for all of them. The others handle different failure
scenarios.
What to study:
• [Link]([p1, p2, p3]) — wait for ALL to resolve. If ANY rejects, immediately rejects.
• [Link]([p1, p2]) — wait for ALL to settle (resolve OR reject). Never rejects.
• [Link]([p1, p2]) — resolves/rejects with the FIRST settled promise
• [Link]([p1, p2]) — resolves with the FIRST fulfilled promise. Rejects only if ALL reject.
• When to use each: all (need all results), allSettled (need all results even with failures), race (timeout
pattern), any (first success wins)
• Practical example: fetching data from multiple APIs in parallel with [Link]()
• Timeout pattern with [Link]([fetch(...), timeoutPromise(5000)])
🔩 Under the Hood — Go here after the surface clicks.
– [Link] internally tracks pending count — when all resolve, it resolves with an array of results
in the same order as input
– [Link] always resolves (never rejects) — each result is { status: 'fulfilled'/'rejected',
value/reason }

📖 Read On: [Link]/promise-api · MDN: [Link] · MDN: [Link]

TOPIC 7 — async / await

What it is:
async/await is syntactic sugar over Promises. An async function always returns a Promise. Inside it, you can
use await to pause execution until a Promise settles — this makes async code look and behave like
synchronous code. It's much more readable than .then() chains for most cases.
What to study:
• async function declaration: async function fetchData() {}
• async arrow: const fetchData = async () => {}
• async functions always return a Promise — even if you return a plain value
• await keyword — pauses the function until the Promise settles. Returns the resolved value.
• await only works inside an async function (or top-level in modules — ES2022)
• Error handling: try/catch around await — catches rejected promises
• Running parallel operations: const [a, b] = await [Link]([fetch1, fetch2])
• MISTAKE: await in a loop one by one — sequential, slow. Use [Link] instead.
• Async IIFE: (async () => { ... })() — run async code at top level
• Top-level await — available in ES modules without wrapping in async function

🔩 Under the Hood — Go here after the surface clicks.


– await is syntactic sugar — the JS engine transforms async/await into a state machine using
Promises and generators
– Each await point is essentially a .then() callback — the function suspends and resumes when the
Promise settles
– async functions return a Promise — the resolved value is whatever you return from the function

📖 Read On: [Link]/async-await · MDN: async function · MDN: await

TOPIC 8 — Error Handling in Async Code


What it is:
Errors in async code are different from synchronous errors. An uncaught rejection in a Promise doesn't crash
your program the same way a thrown error does — it just silently fails (or triggers an unhandledRejection
event). Every async operation needs explicit error handling.
What to study:
• try/catch with async/await — catches rejected promises
• Catching in the call chain — where to put the try/catch
• .catch() on promise chains
• Unhandled promise rejection — what happens and why it's dangerous
• [Link]('unhandledRejection') in [Link] — global handler
• [Link]('unhandledrejection') in browser
• The Error object: message, name, stack properties
• Custom error classes: class NetworkError extends Error {}
• Re-throwing errors — catch, do something, throw again
• Error propagation in Promise chains — rejections skip .then() until .catch()
• The finally block in async code — cleanup that always runs

🔩 Under the Hood — Go here after the surface clicks.


– Why unhandled rejections are dangerous — they indicate a programming error where async
failures are silently swallowed
– [Link] unhandledRejection behavior — newer versions crash the process on unhandled rejection
(like uncaught exceptions)

📖 Read On: [Link]/error-handling · [Link]/promise-error-handling · MDN: Error

TOPIC 9 — Fetch API & HTTP

What it is:
fetch() is the browser's built-in way to make HTTP requests. It returns a Promise. Every MERN application you
build will use fetch (or a library built on it). You need to understand HTTP requests and responses, not just the
fetch() API itself.
What to study:
• What HTTP is — the protocol for sending data between client and server
• HTTP methods: GET (read), POST (create), PUT/PATCH (update), DELETE
• HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500
Server Error
• fetch(url) — basic GET request
• The Response object: [Link], [Link], [Link]
• [Link]() — parse response body as JSON. Returns a Promise.
• [Link](), [Link]() — other response formats
• POST request with fetch: { method: 'POST', headers: {...}, body: [Link](data) }
• Content-Type header: 'application/json' — tells server the format
• CORS — what it is and why fetch sometimes fails cross-origin
• fetch does NOT reject on HTTP errors (404, 500) — check [Link] manually
• Proper error handling: if (![Link]) throw new Error([Link])

🔩 Under the Hood — Go here after the surface clicks.


– fetch() is built on the XMLHttpRequest API in older browsers, but is its own native API in modern
ones
– CORS (Cross-Origin Resource Sharing) — the browser's security mechanism that prevents JS
from making requests to different origins without permission
– The browser sends a preflight OPTIONS request for non-simple requests

📖 Read On: [Link]/fetch · [Link]/fetch-crossorigin · MDN: Fetch API

TOPIC 10 — Advanced Async Patterns

What it is:
Real applications need more than basic fetch and await. Timeout patterns, retry logic, concurrency control,
and cancellation are all patterns you'll need. These are not built into the language — you implement them
using the primitives you've learned.
What to study:
• Timeout pattern: race a fetch against a Promise that rejects after N seconds
• Retry pattern: retry a failed async operation N times with delay
• Exponential backoff — increasing delay between retries
• Concurrency control — limit to N parallel requests at a time
• AbortController — cancel a fetch request in progress
• AbortController with signal: fetch(url, { signal: [Link] })
• Calling [Link]() cancels the fetch
• Sequential vs parallel — knowing when each is appropriate
• Async iterators and for await...of — iterating async data sources
• Throttled fetch — debouncing API calls on user input

🔩 Under the Hood — Go here after the surface clicks.


– AbortController uses the AbortSignal which propagates through the fetch implementation down to
the network layer
– Async generators — function* with async — produce values asynchronously. for await...of
consumes them.

📖 Read On: [Link]/fetch-abort · MDN: AbortController · [Link]/async-iterators-


generators

🏗 UNIT PROJECT — Weather Dashboard using a Real API


Call a real public weather API. Display current weather and 5-day forecast. Handle all the
async complexity — loading states, errors, cancellation.
Features to implement:
• Search by city name — fetch weather from OpenWeatherMap API (free tier)
• Display current: temperature, humidity, wind speed, weather icon, description
• Display 5-day forecast with highs/lows
• Loading state — show spinner while fetching
• Error handling — city not found, network error, API error
• Debounce the search input — don't fetch on every keystroke
• AbortController — cancel previous request when user types a new search
• Save last searched city in localStorage — restore on page load
• Unit toggle: Celsius / Fahrenheit (convert without re-fetching)

This project tests:


– Promises and async/await — all network calls
– Error handling — every failure mode covered
– AbortController — cancel in-flight requests
– Fetch API — real HTTP requests with headers
– Debouncing — a real performance pattern
– DOM manipulation — dynamically building the weather UI
– localStorage — persistence

UNIT 7

Modern JavaScript — ES6 to ES2024


ES6 (2015) was a revolution. ES2016 through ES2024 added important features steadily.
This unit systematically covers every significant modern JS feature. You'll recognize some
from earlier units — here you go deeper.
⏱ Time Estimate: 30–42 hours total (20–30h study + 10–12h project)

By the end of this unit you will:


• Use ES6 modules: import/export — both named and default, and know the difference from
CommonJS
• Use every major destructuring and spread pattern fluently
• Know every significant ES2016–ES2024 feature by name and purpose
• Write and use generators with function* and yield
• Understand Symbols and their practical use cases
• Know the Proxy and Reflect APIs

Study Order — Do These In Sequence

ES6 Modules — import / export


1 The module system — critical for MERN

CommonJS vs ES Modules
2 [Link] uses both — you need to know the difference

Symbols
3 Unique keys — more powerful than they appear

Iterators & The Iteration Protocol


4 How for...of actually works

Generators
5 Functions that can pause and resume

ES2016–ES2024 Features — Complete Survey


6 Every feature worth knowing

Proxy & Reflect


7 Meta-programming — intercepting object operations

TOPIC 1 — ES6 Modules — import / export

What it is:
Modules let you split code across files and control what's public and what's private. Each module has its own
scope — variables don't leak to global. export marks things as public. import brings them in. This is how every
modern JS application is structured.
What to study:
• Named exports: export const name = ... or export { name, fn }
• Default export: export default function() {} — one per module
• Named import: import { name, fn } from './[Link]'
• Default import: import myName from './[Link]' — any name works
• Import both: import defaultExport, { namedExport } from './[Link]'
• Import all: import * as utils from './[Link]'
• Rename on import: import { name as firstName } from './[Link]'
• Re-exporting: export { name } from './[Link]'
• Dynamic imports: import('./[Link]').then(module => ...) — load on demand
• await import('./[Link]') — with top-level await
• Module script type: <script type='module'> — required in browser
• Modules are singletons — importing the same module twice gives the same instance
• Modules are strict mode by default

🔩 Under the Hood — Go here after the surface clicks.


– Static analysis — import/export are static declarations, not function calls. The engine can analyze
the dependency graph before running any code
– Live bindings — named imports are live references to the exported variable. If the export changes,
the import reflects it
– This is different from CommonJS where require() returns a copy of the value
– Module evaluation — each module is evaluated once and cached. Subsequent imports get the
cached module

📖 Read On: [Link]/modules-intro · [Link]/import-export · MDN: JavaScript modules

TOPIC 2 — CommonJS vs ES Modules

What it is:
[Link] was built with CommonJS (require/[Link]) before ES modules existed. ES modules were
added later. Today [Link] supports both, but they behave differently. You'll encounter both in the MERN
stack — React uses ES modules, many [Link] packages still use CommonJS.
What to study:
• CommonJS: const mod = require('./module')
• CommonJS: [Link] = { ... } or [Link] = ...
• CommonJS is synchronous — require() is a blocking operation that runs the module immediately
• ES Modules: import/export — you've just learned these
• ES Modules are asynchronous — loaded and evaluated asynchronously
• File extension: .js can be either (determined by [Link] type field), .cjs is always CommonJS, .mjs
is always ES Module
• [Link]: 'type': 'module' — makes all .js files in the package ES modules
• Mixing them — you CAN import CJS from ESM but not vice versa in some cases
• Why MERN uses both — [Link] server code often CommonJS, React code always ES modules
• Interop: import cjsModule from './[Link]' — default import gets [Link]

🔩 Under the Hood — Go here after the surface clicks.


– CommonJS require() is synchronous — this is why it works in [Link] (server, can block) but not
in browsers (blocking downloads = bad UX)
– ES module loading is asynchronous — parsing, fetching dependencies, and linking happen before
execution
– The module graph — ES modules form a directed acyclic graph that's fully analyzed before
execution begins

📖 Read On: [Link]/api/esm · [Link]/api/modules · MDN: JavaScript modules

TOPIC 3 — Symbols

What it is:
A Symbol is a unique, primitive value created by Symbol(). Every Symbol() call creates a new, unique symbol
— even if you pass the same description. Symbols are primarily used as object property keys that never
conflict with string keys, and for defining special behaviors via 'well-known symbols'.
What to study:
• Creating symbols: const id = Symbol('description')
• Every symbol is unique: Symbol('id') !== Symbol('id')
• Symbols as object keys: obj[id] = value — accessed only via bracket notation
• Symbol properties are hidden from for...in, [Link](), [Link]()
• [Link]() — get symbol keys
• Global symbol registry: [Link]('key') and [Link](sym)
• Well-known symbols — used to customize JS behavior:
• [Link] — makes an object iterable (for...of)
• [Link] — customize type conversion
• [Link] — customize instanceof
• [Link] — customize [Link] output

🔩 Under the Hood — Go here after the surface clicks.


– Well-known symbols are how JS allows you to hook into core language operations without name
collisions
– [Link] is how for...of works — the engine calls [[Link]]() on the object to get an
iterator
– This is the extensibility mechanism that avoids 'magic method name' problems
📖 Read On: [Link]/symbol · MDN: Symbol

TOPIC 4 — Iterators & The Iteration Protocol

What it is:
The iteration protocol is a standard way any object can say 'I am iterable'. An iterable has a [[Link]]()
method that returns an iterator. An iterator has a next() method that returns { value, done }. This is how for...of
works on arrays, strings, Maps, Sets, and generators.
What to study:
• The iterable protocol — an object with [[Link]]() method
• The iterator protocol — an object with next() that returns { value, done }
• Built-in iterables: Array, String, Map, Set, arguments, NodeList
• What for...of does — calls [[Link]](), then repeatedly calls next()
• Destructuring arrays uses the iteration protocol
• Spread on iterables: [...iterable]
• Making a custom iterable object from scratch
• Making an infinite iterator — one that never returns done: true
• Iterator composition — iterators that wrap other iterators

🔩 Under the Hood — Go here after the surface clicks.


– The engine calls [[Link]]() once to get the iterator, then calls .next() on each loop iteration
– Generators automatically implement both protocols — a generator function returns an object that
is both iterable and iterator

📖 Read On: [Link]/iterable · MDN: Iteration protocols

TOPIC 5 — Generators

What it is:
A generator function can pause its execution using yield and resume later. It returns a generator object that
implements the iterator protocol. Generators are useful for lazy sequences, infinite data streams, and they are
the foundation of how async/await was originally implemented.
What to study:
• Generator function syntax: function* myGen() {}
• yield — pauses execution and returns a value to the caller
• next() returns { value, done }
• Resuming with next(value) — pass a value back into the generator
• Generator as iterable — use with for...of, spread
• Finite generators — yield a finite sequence, then done: true
• Infinite generators — while(true) { yield something } — lazy, only computes next when asked
• Generator delegation: yield* anotherGenerator()
• return inside generator — terminates early
• try/finally in generators — finally runs when generator is closed
• throw() on generator — inject an error into the generator
• Practical uses: infinite sequences, lazy evaluation, state machines, co-routines
• async generators: async function* — produces values asynchronously, consumed with for await...of

🔩 Under the Hood — Go here after the surface clicks.


– Generators are state machines — the engine saves and restores the entire execution state at
each yield point
– This is exactly how async/await was first proposed and implemented — as syntactic sugar over
generators + Promises
– The original async/await proposal used generators with a 'runner' like [Link]

📖 Read On: [Link]/generators · [Link]/async-iterators-generators · MDN: function*

TOPIC 6 — ES2016–ES2024 Features — Complete Survey

What it is:
JS evolves every year. TC39 (the standards committee) adds features through a proposal process. Here is
every feature from ES2016 to ES2024 that you need to know, organized by year.
What to study:
• ES2016: [Link]() — includes(value) returns boolean (better than indexOf()).
Exponentiation operator **
• ES2017: [Link](), [Link](). [Link]() / padEnd(). Trailing commas in
function params. Async functions (async/await).
• ES2018: Rest/spread for objects. [Link](). Async iteration (for await...of). RegExp named
groups (?<name>), lookbehind assertions.
• ES2019: [Link]() / flatMap(). [Link](). [Link]() / trimEnd(). Optional
catch binding: catch { } instead of catch(e) { }. [Link]() now guaranteed stable.
• ES2020: BigInt. Optional chaining (?.). Nullish coalescing (??). [Link](). globalThis.
Dynamic import(). [Link]().
• ES2021: [Link](). [Link](). Logical assignment operators: &&=, ||=, ??=. WeakRef and
FinalizationRegistry. Numeric separators: 1_000_000.
• ES2022: Top-level await in modules. Class fields and private (#). Static class blocks. [Link]().
[Link](). Error cause: new Error('msg', { cause: originalError }). RegExp /d flag (indices).
• ES2023: [Link]() / findLastIndex(). [Link](), toReversed(), toSpliced(), with() — non-
mutating versions. [Link] / using declaration.
• ES2024: [Link](). [Link]() / [Link](). [Link]().
RegExp v flag.
🔩 Under the Hood — Go here after the surface clicks.
– TC39 proposal process — stage 0 (idea) → stage 1 (proposal) → stage 2 (draft) → stage 3
(candidate) → stage 4 (finished). Features at stage 4 are added to the spec.
– Browser compatibility — not all features are available everywhere. Check: [Link] and MDN
compatibility tables.
– Transpilers like Babel — transform new JS syntax to older syntax for compatibility

📖 Read On: [Link]/proposals (finished proposals) · MDN: What's new in JavaScript · [Link]

TOPIC 7 — Proxy & Reflect

What it is:
Proxy lets you intercept and redefine fundamental operations on objects — property access, assignment,
deletion, function calls. Reflect provides methods that mirror these same operations. Together they enable
meta-programming: writing code that controls how other code behaves.
What to study:
• Proxy: const proxy = new Proxy(target, handler)
• Handler traps: get, set, has, deleteProperty, apply, construct
• get trap: intercept property reads — return custom values or log access
• set trap: intercept property writes — validate before storing
• has trap: intercept the 'in' operator
• deleteProperty trap: intercept delete operator
• apply trap: intercept function calls (target must be a function)
• Reflect API: [Link](), [Link](), [Link](), etc.
• Using Reflect inside traps — always call Reflect to perform the default operation after your custom logic
• Revocable proxies: [Link]() — create a proxy you can disable
• Practical uses: validation, logging, default values for missing properties, reactive data (how [Link] 3
works)
• Proxy limitations — cannot trap private fields (#), some internal operations

🔩 Under the Hood — Go here after the surface clicks.


– [Link] 3 uses Proxy to implement reactive state — when you set a property, the Proxy trap
triggers UI updates
– [Link]() was the predecessor to Proxy — it was withdrawn from the spec because Proxy
is more powerful
– Proxy traps correspond directly to internal methods in the ECMAScript spec: [[Get]], [[Set]],
[[HasProperty]], etc.

📖 Read On: [Link]/proxy · MDN: Proxy · MDN: Reflect


🏗 UNIT PROJECT — Module-Based Todo App
Build a full todo application using ES modules — each concern in its own file. Focus on clean
architecture and using every modern JS feature naturally.
Features to implement:
• Separate modules: [Link], [Link], [Link], [Link], [Link]
• CRUD: add todo, complete, delete, edit
• Filtering: All / Active / Completed
• Sorting: by date, by priority, by name
• Persist to localStorage with JSON
• Drag and drop to reorder (use events)
• Due dates with overdue highlighting
• Tag/category system using a Set to track unique tags
• Keyboard shortcuts (no mouse required for power users)
• Search/filter todos as you type (debounced)

This project tests:


– ES Modules — proper separation of concerns
– Modern syntax — optional chaining, nullish coalescing, destructuring everywhere
– Proxy — optionally: use Proxy for reactive state
– Symbols — use a Symbol for internal todo IDs
– Generators — generate unique IDs with a generator
– Set — for tag management
– Map — for O(1) todo lookup by ID

UNIT 8

Advanced Concepts & Patterns


This is senior-level territory. Execution context, memory management, functional
programming, design patterns, performance optimization, and regular expressions. These
topics separate developers who write JS from developers who truly understand it.
⏱ Time Estimate: 60–85 hours total (40–60h study + 20–25h project)

By the end of this unit you will:


• Fully understand execution context, variable environments, and hoisting at the engine level
• Understand garbage collection and identify/prevent memory leaks
• Write functional JS: pure functions, immutability, composition, currying
• Recognize and implement key design patterns in JS
• Optimize code using debounce, throttle, memoization, and lazy evaluation
• Write and use regular expressions confidently

Study Order — Do These In Sequence

Execution Context & Variable Environments


1 The deepest look at how JS runs code

Hoisting — The Full Picture


2 Everything that gets hoisted and why

Memory Management & Garbage Collection


3 How memory is allocated and freed

Functional Programming
4 A different way to think about code

Currying & Partial Application


5 Advanced function composition techniques

Design Patterns
6 Proven solutions to recurring problems

Performance: Debounce, Throttle, Memoize


7 Real patterns for real performance problems

Regular Expressions
8 Pattern matching — powerful and necessary

Error Handling Architecture


9 Building robust error handling into large applications

TOPIC 1 — Execution Context & Variable Environments


What it is:
An execution context is the environment in which JS code runs. Every function call creates a new execution
context. Understanding the creation and execution phases of an execution context explains hoisting, closure,
and how 'this' is determined — all at once.
What to study:
• The Global Execution Context — created on startup. Creates the global object and 'this'.
• Function Execution Contexts — created on every function call
• The Execution Context Stack (call stack) — the stack of active contexts
• Creation Phase vs Execution Phase:
• Creation: allocate memory for variables and functions, set up scope chain, determine 'this'
• Execution: run code line by line, assign values
• Variable Environment — stores variables and function declarations for the context
• Lexical Environment — stores variables + outer reference (scope chain)
• How the scope chain is created — each context stores a reference to its outer context's Lexical
Environment
• Environment Records — the actual storage for variables in a scope

🔩 Under the Hood — Go here after the surface clicks.


– In the ECMAScript spec, an execution context has: code evaluation state, function/script/module,
Realm, Lexical Environment, Variable Environment
– The outer environment reference is what creates the scope chain — it's set when the function is
DEFINED, not called (lexical scoping)
– Read: [Link]/ecma262 section on Execution Contexts
– Read: [Link]/closure — the Lexical Environment sections go deep here

📖 Read On: [Link]/closure · [Link]/ecma262 (Execution Contexts section) · MDN: Scope

TOPIC 2 — Hoisting — The Full Picture

What it is:
Hoisting is the result of the creation phase — before any code runs, JS sets up variable and function
declarations. The behavior differs between var, let, const, function declarations, function expressions, and
class declarations. Getting this completely straight prevents a category of subtle bugs.
What to study:
• Function declarations are fully hoisted — available before their definition in code
• var is hoisted and initialized to undefined — can be used before assignment (value is undefined)
• let and const are hoisted but NOT initialized — in the Temporal Dead Zone until their declaration
• Temporal Dead Zone (TDZ) — the period between entering scope and the declaration line
• Accessing a let/const in the TDZ throws a ReferenceError
• Function expressions (var fn = function(){}) — hoisted as var, undefined until assignment line
• Class declarations — hoisted but in TDZ (like let/const), cannot be used before declaration
• Hoisting inside blocks — let/const are block-scoped and hoisted to the top of their block
• Hoisting order: function declarations are processed before var declarations in the same scope

🔩 Under the Hood — Go here after the surface clicks.


– Hoisting is the visible effect of the creation phase — the engine processes declarations before
execution begins
– var declarations are added to the Variable Environment record and initialized to undefined during
creation
– let/const declarations are added to the Lexical Environment but NOT initialized — access before
initialization reads from the uninitialized binding, which throws

📖 Read On: [Link]/var · MDN: Hoisting · [Link]/closure

TOPIC 3 — Memory Management & Garbage Collection

What it is:
JS manages memory automatically — you don't call malloc/free like in C++. The garbage collector (GC)
automatically frees memory that is no longer reachable. Understanding how it works helps you avoid memory
leaks — situations where you accidentally hold references to things you no longer need.
What to study:
• Memory lifecycle: allocate → use → release
• Automatic allocation — JS allocates when you declare variables, create objects, call functions
• The Mark and Sweep algorithm — the GC marks all reachable objects from roots, sweeps away the
rest
• Roots — global variables, the call stack, and any references from those
• Memory leaks — holding unnecessary references that prevent GC from collecting objects
• Common memory leak sources:
• Accidental global variables — assigning without var/let/const in non-strict mode
• Forgotten timers — setInterval referencing objects, never cleared
• DOM references — storing reference to removed DOM node
• Closures holding large objects in scope unnecessarily
• Event listeners not removed
• WeakRef — a reference that doesn't prevent GC
• FinalizationRegistry — callback when a weakly-referenced object is collected
• Detecting leaks — using Chrome DevTools Memory panel, heap snapshots

🔩 Under the Hood — Go here after the surface clicks.


– V8 uses generational garbage collection — young generation (most objects die young, collected
frequently with Scavenge) and old generation (long-lived objects, collected with Mark-Sweep-
Compact)
– Incremental marking — GC runs in small increments to avoid long pauses
– Concurrent marking — GC marks objects on background threads while JS runs
– Read: [Link]/blog/trash-talk — V8's garbage collector explained

📖 Read On: [Link]/garbage-collection · MDN: Memory Management · [Link]/blog/trash-talk

TOPIC 4 — Functional Programming

What it is:
Functional programming (FP) is a programming paradigm that treats computation as the evaluation of
functions and avoids mutable state and side effects. JS supports FP alongside OOP. Many modern JS
patterns (especially in React) are heavily functional.
What to study:
• Pure functions — same input, always same output. No side effects.
• Side effects — anything that affects the outside world: network calls, file writes, DOM changes,
modifying outer variables
• Immutability — never mutate data, always create new data
• Immutable updates for objects: { ...original, changedProp: newValue }
• Immutable updates for arrays: [...[Link](0,i), newItem, ...[Link](i+1)]
• Function composition — combining simple functions to build complex ones
• compose(f, g)(x) = f(g(x)) — right to left
• pipe(f, g)(x) = g(f(x)) — left to right
• Avoiding shared state — each function works with its arguments, not external variables
• Functors — things that can be mapped over (arrays implement map = they are functors)
• Point-free style — defining functions without mentioning their arguments
• Referential transparency — a function call can be replaced with its return value without changing
behavior

🔩 Under the Hood — Go here after the surface clicks.


– FP and optimization — pure functions are trivially memoizable and parallelizable
– FP in the spec — JS's Array methods (map, filter, reduce) are defined in a purely functional style
in the spec

📖 Read On: [Link]/ · mostly-adequate-guide (free FP book for JS):


[Link]/MostlyAdequate/mostly-adequate-guide

TOPIC 5 — Currying & Partial Application

What it is:
Currying transforms a function that takes multiple arguments into a sequence of functions each taking one
argument: f(a, b) becomes f(a)(b). Partial application pre-fills some arguments of a function, returning a new
function for the rest. Both are tools for creating specialized functions from general ones.
What to study:
• Currying: const add = a => b => a + b — add(3)(4) = 7
• Why currying is useful — creating specialized versions of general functions
• curry(fn) — writing a utility function that curries any function
• Partial application with bind: const add5 = [Link](null, 5)
• Partial application without bind: const partial = (fn, ...args) => (...rest) => fn(...args, ...rest)
• Difference: currying always takes one argument at a time, partial applies some arguments at once
• Real use: event handlers with data: [Link](item => [Link]('click',
handleClick(item)))
• Function composition with curried functions

🔩 Under the Hood — Go here after the surface clicks.


– Currying is implemented using closures — each returned function closes over the argument from
the previous call
– Lodash's _.curry() auto-curries based on function arity ([Link]) — detect when all args are
provided and call the original

📖 Read On: [Link]/currying-partials · MDN: Partial application

TOPIC 6 — Design Patterns

What it is:
Design patterns are proven, reusable solutions to commonly occurring problems in software design. They are
not code you copy — they are concepts you apply. Knowing these gives you a vocabulary for discussing code
architecture and a toolkit for solving structural problems.
What to study:
• Module Pattern — encapsulate private state using closures. The basis of all JS modules before ES6.
• Singleton Pattern — ensure only one instance exists. Often implemented with closures or modules.
• Observer / Pub-Sub Pattern — objects subscribe to events, publisher notifies all subscribers.
Foundation of event systems.
• Factory Pattern — a function that creates and returns objects. Alternative to new and classes.
• Builder Pattern — construct complex objects step by step through chained methods.
• Strategy Pattern — define a family of algorithms, encapsulate each, make them interchangeable.
• Decorator Pattern — add behavior to an object without changing its class (not to be confused with class
decorators).
• Command Pattern — encapsulate requests as objects. Enables undo/redo.
• Iterator Pattern — traverse a collection without exposing its internal structure (you know this — it's the
iteration protocol).
• Mediator Pattern — objects communicate through a central mediator instead of directly.
• Proxy Pattern — you know this — it's the Proxy API.
• Mixin Pattern — add methods from multiple sources to a class without inheritance.

🔩 Under the Hood — Go here after the surface clicks.


– Most JS patterns exist to solve problems that disappear in OOP languages with proper
encapsulation, multiple inheritance, or interfaces
– ES6 classes, modules, and Proxy make many classic patterns cleaner or obsolete
– Read: [Link] — modern JS design and architecture patterns

📖 Read On: [Link] · [Link]/pattern-syntax · [Link]/design-patterns/javascript

TOPIC 7 — Performance: Debounce, Throttle & Lazy Evaluation

What it is:
Real applications have performance problems. Debounce delays a function call until a pause in activity.
Throttle limits how often a function can be called. Lazy evaluation avoids computing values until they're
needed. These are tools you'll use in every production application.
What to study:
• Debounce — delay execution until N ms after the LAST call. Use case: search-as-you-type, resize
handler
• Implementing debounce from scratch using setTimeout and clearTimeout
• Throttle — execute at most once per N ms. Use case: scroll handler, game loop, rate-limited API
• Implementing throttle from scratch
• Debounce vs Throttle — which to use when
• Memoization — cache results of expensive function calls by their arguments
• Memoize with Map: key is serialized args, value is result
• Memoize with WeakMap for object arguments
• Lazy evaluation — don't compute until needed. Generators are lazy.
• requestAnimationFrame — run code before the next repaint. Better than setTimeout for animations.
• Web Workers — offload heavy computation to a background thread
• Profiling with DevTools — Performance panel, CPU profiling, memory profiling
• Common performance anti-patterns: DOM manipulation in loops, synchronous XHR, blocking the main
thread

🔩 Under the Hood — Go here after the surface clicks.


– Debounce uses the event loop — it schedules a macrotask (setTimeout) and cancels the previous
one
– requestAnimationFrame callback is called before the browser's next paint — part of the rendering
pipeline, separate from the task queue
– Web Workers run on a separate OS thread with their own event loop — they communicate with
the main thread via postMessage
📖 Read On: [Link]/settimeout-setinterval · MDN: requestAnimationFrame · MDN: Web Workers
API · [Link]/performance

TOPIC 8 — Regular Expressions

What it is:
Regular expressions (regex) are patterns for matching text. They're powerful for validation, parsing, and find-
replace operations. JS has built-in regex support via the RegExp object and regex literals. You can't avoid
them in real development.
What to study:
• Creating regex: /pattern/flags or new RegExp('pattern', 'flags')
• Flags: g (global, all matches), i (case-insensitive), m (multiline), s (dotAll), u (unicode), d (indices)
• Character classes: \d (digit), \w (word char), \s (whitespace), \D \W \S (negated), . (any char)
• Custom character class: [abc], [a-z], [^abc] (negated)
• Quantifiers: * (0+), + (1+), ? (0 or 1), {n}, {n,}, {n,m}
• Greedy vs lazy quantifiers: .* vs .*?
• Anchors: ^ (start), $ (end), \b (word boundary)
• Groups: (pattern) — capturing group. (?:pattern) — non-capturing
• Named groups: (?<name>pattern) — access via [Link]
• Alternation: a|b — match a or b
• Lookahead: (?=pattern) — assert without consuming. Negative: (?!pattern)
• Lookbehind: (?<=pattern). Negative: (?<!pattern)
• Backreferences: \1 — match what group 1 matched
• Methods: [Link](), [Link](), [Link](), [Link](), [Link](), [Link](), [Link]()
• Using [Link] to test and debug patterns

🔩 Under the Hood — Go here after the surface clicks.


– Regex engines use NFA (Non-deterministic Finite Automaton) or DFA (Deterministic Finite
Automaton)
– Catastrophic backtracking — certain regex patterns can have exponential time complexity with
specific inputs. ReDoS (Regex Denial of Service).
– The sticky flag 'y' and lastIndex property — for sequential regex matching

📖 Read On: [Link]/regexp-introduction · MDN: Regular expressions · [Link]

TOPIC 9 — Error Handling Architecture

What it is:
In small scripts, try/catch in one place is fine. In a real application, you need a systematic approach: custom
error classes for different failure types, consistent error handling across async code, meaningful error
messages, and global fallback handlers.
What to study:
• Custom error classes: class ValidationError extends Error { constructor(message, field) {} }
• instanceof for error type checking: catch(e) { if (e instanceof ValidationError) {} }
• Error wrapping — catch a low-level error and re-throw as a higher-level one
• Error cause (ES2022): throw new Error('Failed', { cause: originalError })
• Result type pattern — return { data, error } instead of throwing (functional error handling)
• Global error boundaries — try/catch at the top level of your application
• [Link] and [Link]('error') — browser global error handler
• [Link]('unhandledrejection') — catch unhandled Promise rejections
• Logging errors — what to log, how to log, structured error objects
• Error codes vs error messages — when to use each

🔩 Under the Hood — Go here after the surface clicks.


– The Error object has a stack property — the stack trace is captured at the point the error is
CREATED, not thrown
– Stack traces in async code — async stack traces are assembled by the engine from the microtask
continuation points
– [Link]() (V8 only) — capture a stack trace at a specific point

📖 Read On: [Link]/error-handling · [Link]/custom-errors · MDN: Error

🏗 UNIT PROJECT — Infinite Scroll News Feed


Fetch articles from a public API. Display them in an infinite scroll feed. Apply debounce, throttle,
intersection observer, error handling, and multiple design patterns.
Features to implement:
• Fetch articles from NewsAPI or HackerNews API
• Render articles as cards in a feed
• Infinite scroll — load more when user scrolls to bottom (use IntersectionObserver, not
scroll event)
• Search bar — debounced, cancels in-flight requests with AbortController
• Category filter — throttled, memoized results per category
• Skeleton loading — placeholder UI while fetching
• Error states — network error, empty results, rate limit
• Article bookmarking — save to localStorage, persist across sessions
• Observer pattern — all UI components subscribe to a central state store
• Retry with exponential backoff on failed requests
This project tests:
– Debounce and throttle — real implementations, not library imports
– Memoization — cache API results by query string
– Observer pattern — centralized state management
– AbortController — cancel in-flight fetches
– IntersectionObserver API — trigger actions when elements enter the viewport
– Async/await + error handling — every failure mode handled
– Modular architecture — separate files for API, store, components, utils

UNIT 9

[Link] — JavaScript on the Server


You've mastered browser JS. Now the same language runs on a server. [Link] brings
JS to the backend using the same V8 engine. This unit leads directly into [Link] and
the full MERN stack.
⏱ Time Estimate: 45–60 hours total (30–40h study + 15–20h project)

By the end of this unit you will:


• Run and understand [Link] server-side JavaScript
• Understand how [Link]'s event loop differs from the browser's
• Work with the file system, paths, and environment variables
• Create a basic HTTP server from scratch
• Understand npm and manage packages professionally
• Know the difference between CommonJS and ES Modules in Node
• Understand what [Link] solves and build a basic server with it

Study Order — Do These In Sequence

[Link] Runtime & Global Objects


1 How Node differs from the browser

[Link] Event Loop — The Differences


2 The Node event loop has more phases than the browser

3 Module System — CommonJS & ESM in Node


Both systems, how they interact

npm — Node Package Manager


4 Managing dependencies professionally

Built-in Modules: fs, path, os


5 Working with the file system and environment

Streams & Buffers


6 Handling large data efficiently

Building an HTTP Server from Scratch


7 Understand what Express does by doing it manually first

Hello [Link]
8 The framework that runs most [Link] servers

Environment Variables & Configuration


9 The professional way to configure Node apps

Debugging & Developer Tools


10 Debugging [Link] like a professional

TOPIC 1 — [Link] Runtime & Global Objects

What it is:
[Link] is a JavaScript runtime built on V8. It gives JS capabilities it doesn't have in the browser: file system
access, network sockets, OS interaction. But it removes browser-specific things: no window, no document, no
DOM. Different globals exist instead.
What to study:
• Installing [Link] — use nvm (node version manager) to manage multiple versions
• Running a file: node [Link]
• The REPL — interactive Node shell: just type node
• Global objects in Node: global (equivalent to window), process, __dirname, __filename
• process object: [Link] (command line args), [Link] (environment variables), [Link](),
[Link]()
• [Link] — parsing command line arguments
• console in Node — same as browser: [Link], [Link], [Link], [Link]
• No window, no document, no XMLHttpRequest, no fetch (added in Node 18+)
• Buffer — Node's way of handling binary data
• global vs globalThis — globalThis works in both Node and browser

🔩 Under the Hood — Go here after the surface clicks.


– [Link] architecture: V8 (JS execution) + libuv (async I/O, event loop) + [Link] built-in modules
(C++ bindings)
– Node's C++ layer — built-in modules like fs and http are implemented in C++ with JS bindings
– Read: [Link]/en/docs/guides/anatomy-of-an-http-transaction

📖 Read On: [Link]/docs · [Link]/nodejs

TOPIC 2 — [Link] Event Loop — The Differences

What it is:
The [Link] event loop is based on libuv, not the browser's HTML spec. It has the same basic concept (call
stack → queue → event loop) but with more phases. Understanding these phases explains why some
callbacks run before others in Node.
What to study:
• Node's event loop phases (in order): timers → pending callbacks → idle/prepare → poll → check →
close callbacks
• timers phase — executes setTimeout and setInterval callbacks whose delay has passed
• poll phase — retrieves new I/O events, executes their callbacks. Node waits here if nothing else to do.
• check phase — executes setImmediate() callbacks
• setImmediate vs setTimeout(fn, 0) — setImmediate runs in check phase (after I/O). setTimeout in
timers phase.
• [Link]() — NOT part of the event loop. Runs after current operation, before I/O events.
Higher priority than Promises.
• Priority order: [Link] > Promise microtasks > setImmediate > setTimeout(fn,0)
• Why [Link] can starve the event loop — infinite nextTick recursion prevents I/O from ever
being processed

🔩 Under the Hood — Go here after the surface clicks.


– libuv — the C library that handles async I/O for [Link]. It has a thread pool (4 threads by default)
for operations the OS can't do async (file I/O, DNS, crypto).
– The libuv thread pool — UV_THREADPOOL_SIZE environment variable controls it
– Network I/O uses kernel async mechanisms (epoll/kqueue) and does NOT use the thread pool
– Read: [Link]/en/docs/guides/event-loop-timers-and-nexttick
📖 Read On: [Link]/en/docs/guides/event-loop-timers-and-nexttick · MDN: [Link] Event Loop

TOPIC 3 — Module System — CommonJS & ESM in Node

What it is:
[Link] originally used CommonJS (require/[Link]). ES Modules (import/export) were added later.
Both coexist in modern Node. You need to know both because you'll encounter both in the wild, and mixing
them has rules.
What to study:
• CommonJS: const x = require('./module'); [Link] = ...; exports.x = ...
• CommonJS modules are cached — require() the same file twice returns the same cached exports
• CommonJS is synchronous — require() blocks until the module is evaluated
• ES Modules in Node: add 'type': 'module' in [Link] OR use .mjs extension
• ESM uses import/export — async, statically analyzed
• Importing CJS from ESM: works, default import gets [Link]
• Importing ESM from CJS: does NOT work directly (CJS is sync, ESM is async)
• Circular dependencies — how both systems handle them (and the bugs they cause)
• [Link]() — find the file path of a module without loading it
• __dirname and __filename in ESM — not available. Use [Link] instead.
• [Link] — the URL of the current module file

🔩 Under the Hood — Go here after the surface clicks.


– CommonJS module wrapping — Node wraps every CJS module in a function: (function(exports,
require, module, __filename, __dirname) { ... })
– This is why __dirname and exports exist — they're injected via the wrapper function
– CJS module caching — stored in [Link] keyed by resolved file path

📖 Read On: [Link]/api/modules · [Link]/api/esm

TOPIC 4 — npm — Node Package Manager

What it is:
npm is the package manager for [Link] and the largest software registry in the world. Understanding npm
properly — not just 'npm install' — is a professional skill. You need to understand the [Link] fields,
semantic versioning, the lock file, and how the node_modules directory works.
What to study:
• npm init and npm init -y — create a [Link]
• [Link] fields: name, version, description, main, scripts, dependencies, devDependencies,
engines
• npm install — install all dependencies. npm install packageName — add a dependency
• npm install --save-dev — add a devDependency (only needed for development, not in production)
• Semantic versioning: [Link] — 2.3.1
• Version ranges in [Link]: ^2.3.1 (minor+patch updates OK), ~2.3.1 (patch updates only), 2.3.1
(exact)
• [Link] — locks exact versions of all dependencies (and their dependencies)
• Why you commit [Link] — ensures everyone installs the same versions
• node_modules — where installed packages live. Never commit this folder.
• .npmrc — npm configuration file
• npm scripts: 'scripts': { 'start': 'node [Link]', 'test': 'jest' } — run with npm run start
• npx — run a package without installing it globally
• npm audit — check for security vulnerabilities in dependencies
• npm update — update packages within version ranges
• Global installs: npm install -g packageName — available system-wide

🔩 Under the Hood — Go here after the surface clicks.


– npm install resolves the dependency tree, downloads tarballs from the registry, extracts them to
node_modules
– Nested node_modules — packages can have their own node_modules for different version
requirements
– The registry — [Link] serves package metadata and tarballs. npm can be configured to use
private registries.

📖 Read On: [Link] · [Link]/api/packages

TOPIC 5 — Built-in Modules: fs, path, os

What it is:
[Link] ships with built-in modules for common server tasks. fs handles the file system. path handles file path
manipulation (crucial for cross-platform code). os gives system information. These are your tools before
installing any packages.
What to study:
• fs — file system:
• [Link](path, 'utf8', callback) — async read
• [Link](path, 'utf8') — sync read (blocks thread)
• [Link](path, data, callback) — async write
• [Link](), [Link](), [Link](), [Link]()
• [Link] — promisified versions: await [Link](...)
• fs/promises module — cleaner import for promise versions
• [Link]() — watch files for changes
• path — path manipulation:
• [Link]('dir', 'subdir', '[Link]') — cross-platform path joining
• [Link]() — absolute path resolution
• [Link](), [Link](), [Link]()
• [Link]() — break a path into components
• __dirname — current directory (CJS). [Link] + fileURLToPath for ESM.
• os module — system info:
• [Link](), [Link](), [Link](), [Link](), [Link](), [Link]()

🔩 Under the Hood — Go here after the surface clicks.


– [Link] uses libuv's thread pool — the actual disk I/O happens on a background thread
– [Link] blocks the entire [Link] event loop — never use in a server that handles multiple
requests
– [Link] uses the OS-specific separator (/ on Unix, \ on Windows) — always use [Link], never
string concatenation for paths

📖 Read On: [Link]/api/fs · [Link]/api/path · [Link]/api/os

TOPIC 6 — Streams & Buffers

What it is:
A Buffer is a fixed-size chunk of raw binary memory — Node's way of working with binary data. A Stream is a
sequence of data available over time. Instead of waiting for all data before processing, streams let you
process data as it arrives — essential for large files or network data.
What to study:
• Buffer — raw binary data: [Link]('hello'), [Link](16)
• Buffer encoding: utf8, hex, base64
• Why Buffers exist — Node handles binary data (files, network) before encoding to string
• Streams — four types: Readable, Writable, Duplex, Transform
• Reading a stream: [Link]('data', chunk => ...) and [Link]('end', () => ...)
• pipe() — connect a readable stream to a writable: [Link](writeStream)
• [Link]() and [Link]() — file streams
• Why streams matter — reading a 4GB file: readFileSync crashes (runs out of memory), a stream
processes it chunk by chunk
• Backpressure — when the consumer is slower than the producer, streams handle the buffering
• Transform streams — read, transform, write: like a zlib gzip compressor

🔩 Under the Hood — Go here after the surface clicks.


– Streams use an internal Buffer to hold chunks between read and write operations
– The highWaterMark option — the buffer size threshold that triggers backpressure
– Node streams implement the EventEmitter pattern internally

📖 Read On: [Link]/api/stream · [Link]/api/buffer

TOPIC 7 — Building an HTTP Server from Scratch

What it is:
Before using Express, build a server manually with Node's built-in http module. This shows you exactly what
Express abstracts away — routing, parsing request bodies, setting response headers. Doing this once means
you'll never be confused by what Express is doing.
What to study:
• [Link]((req, res) => { ... }) — create a server
• req object: [Link], [Link], [Link]
• res object: [Link](statusCode, headers), [Link](data), [Link](data)
• Content-Type header — telling the client what format the response is in
• Manual routing: if ([Link] === '/users' && [Link] === 'GET') { ... }
• Parsing the request body — data comes as a stream: collect chunks, join on 'end'
• Parsing JSON body: [Link](body)
• URL parsing: new URL([Link], '[Link]
• Query string parsing: [Link]('name')
• [Link](port, hostname, callback) — start listening
• Returning JSON: [Link](200, { 'Content-Type': 'application/json' });
[Link]([Link](data))
• 404 for unmatched routes

🔩 Under the Hood — Go here after the surface clicks.


– [Link]() creates a TCP server using libuv — it listens for connections and emits
'request' events
– The request body streams in chunks — you must collect them manually (or use a framework that
does it for you)
– This is exactly what Express does internally with its Router and bodyParser middleware

📖 Read On: [Link]/api/http · [Link]/en/docs/guides/anatomy-of-an-http-transaction

TOPIC 8 — Hello [Link]

What it is:
Express is the most popular [Link] web framework. It wraps Node's http module and adds routing,
middleware, request/response helpers, and a clean API. After building an http server from scratch, Express
will feel like a breath of fresh air.
What to study:
• Installing Express: npm install express
• Creating an Express app: const app = express()
• Defining routes: [Link]('/users', (req, res) => { ... })
• HTTP method routing: [Link](), [Link](), [Link](), [Link](), [Link]()
• Route parameters: [Link]('/users/:id', (req, res) => { [Link] })
• Query parameters: [Link]
• Request body: [Link] — requires middleware to parse
• [Link]() middleware — parse JSON request bodies
• [Link]() — parse form data
• [Link](data) — send JSON response
• [Link](404).json({ error: 'Not Found' }) — status + JSON
• [Link]() — mount middleware
• Middleware concept — functions that run between request and response
• [Link](3000, () => [Link]('Server running'))
• Express Router — splitting routes across multiple files

🔩 Under the Hood — Go here after the surface clicks.


– Express middleware is a chain of functions — each calls next() to pass to the next middleware
– [Link]() reads the request stream, parses JSON, and attaches to [Link]
– Express Router creates sub-applications with their own middleware stack
– Error-handling middleware has 4 parameters: (err, req, res, next) — Express detects this by arity

📖 Read On: [Link]/en/starter/[Link] · [Link]/en/guide/[Link]

TOPIC 9 — Environment Variables & Configuration

What it is:
Configuration that changes between environments (development, production) should never be hardcoded.
API keys, database URLs, port numbers — these go in environment variables. The dotenv package loads
them from a .env file in development.
What to study:
• [Link] — object with all environment variables
• Setting env vars: export PORT=3000 (Unix) or set PORT=3000 (Windows)
• The .env file — key=value pairs, one per line
• dotenv package: require('dotenv').config() — loads .env into [Link]
• .gitignore — always add .env to this. Never commit secrets.
• .[Link] — commit this with dummy values so others know what variables are needed
• Accessing: const PORT = [Link] || 3000 — fallback to default
• NODE_ENV variable — 'development', 'production', 'test' — controls app behavior
• config management for larger apps — organizing many environment variables

🔩 Under the Hood — Go here after the surface clicks.


– Environment variables are set by the OS and inherited by child processes
– dotenv reads the .env file and calls [Link] = value for each line
– In production (Heroku, AWS, etc.) — set env vars through the platform, not a .env file

📖 Read On: [Link]/package/dotenv · [Link]/api/process#processenv

TOPIC 10 — Debugging & Developer Tools

What it is:
Real code has bugs. Knowing how to debug efficiently is as important as knowing how to write code. [Link]
has a built-in debugger, VS Code has excellent [Link] debugging support, and there are logging tools you
should know.
What to study:
• [Link] is not a debugging strategy — but [Link], [Link], [Link] are useful
• [Link] built-in debugger: node inspect [Link]
• VS Code debugger — create [Link] for [Link]. Set breakpoints, step through code.
• Attaching VS Code to a running process: node --inspect [Link] then attach in VS Code
• Chrome DevTools for Node — open chrome://inspect when running with --inspect
• Debugger statement: debugger; — pauses execution when DevTools is open
• nodemon — automatically restart Node when files change: npx nodemon [Link]
• Environment-specific logging: only log verbose info in development
• Error stack traces — reading them, understanding file:line references
• Debugging async code — async stack traces, checking unhandled rejection logs

🔩 Under the Hood — Go here after the surface clicks.


– --inspect flag enables the V8 Inspector Protocol — a WebSocket-based protocol that Chrome
DevTools and VS Code use to connect to the running JS engine
– This is the same protocol used for browser JS debugging

📖 Read On: [Link]/en/docs/guides/debugging-getting-started ·


[Link]/docs/nodejs/nodejs-debugging
🏗 UNIT PROJECT — REST API Server — No Express, Then With Express
Build a REST API from scratch using only Node's http module. Then rebuild it with Express.
This cements the difference and shows you exactly what Express provides.
Features to implement:
• PART 1 — Raw http module:
• GET /tasks — list all tasks (return JSON array)
• POST /tasks — create task (parse JSON body manually)
• GET /tasks/:id — get one task
• PATCH /tasks/:id — update task
• DELETE /tasks/:id — delete task
• Persist tasks to a JSON file using fs module
• PART 2 — Rebuild with Express:
• Same routes, same logic, much cleaner code
• Add [Link]() middleware
• Add error handling middleware
• Split routes into a separate router file
• Add dotenv for PORT configuration
• Add nodemon for development

This project tests:


– [Link] http module — raw server creation, request parsing
– fs module — reading and writing JSON files for persistence
– [Link] — routing, middleware, response helpers
– Streams — manually reading request body in Part 1
– Environment variables — dotenv for configuration
– REST principles — proper HTTP methods and status codes
– Debugging — use VS Code debugger to step through at least one request

All 9 Projects — At A Glance


Unit Project Core Tests Est. Hours

1 Number Guessing Variables, type coercion, control 6–8h


Game flow, truthy/falsy

2 Calculator with History All function types, closures, HOF, 10–15h


map/filter on history

3 Student Grade Manager Objects, arrays, Map, destructuring, 10–12h


JSON, closures

4 Quiz App (Browser) DOM, events, delegation, 12–16h


localStorage, setInterval

5 Bank Account System Classes, inheritance, private fields, 10–15h


static, getters
6 Weather Dashboard Async/await, Fetch, 15–20h
AbortController, error handling,
debounce

7 Module-Based Todo ES Modules, modern syntax, 10–12h


App Symbols, Generators, Set/Map

8 Infinite Scroll News Debounce, throttle, memoize, 20–25h


Feed Observer pattern, retry

9 REST API — Raw + http module, fs, streams, Express, 15–20h


Express dotenv, nodemon

Time Estimates — Deep Mastery Track


Unit Topic Deep Study Project Total

1 Foundations & Syntax 15–20h 6–8h 21–28h

2 Functions 30–40h 10–15h 40–55h

3 Objects & Arrays 25–35h 10–12h 35–47h

4 The DOM & Browser 25–35h 12–16h 37–51h

5 OOP in JavaScript 30–40h 10–15h 40–55h

6 Async JavaScript 40–55h 15–20h 55–75h

7 Modern JS ES6–2024 20–30h 10–12h 30–42h

8 Advanced Patterns 40–60h 20–25h 60–85h

9 [Link] 30–40h 15–20h 45–60h

TOTAL 255–355h 108–143h 363–498h

At 2 hours/day consistently → 7–9 months to complete the full deep track.


At 3 hours/day → 4–6 months. These are not tutorial hours — they are hours of genuine struggle,
building, and understanding.

Master Resource List


Resource Best For URL / How to Access

[Link] PRIMARY resource. Complete, [Link]


modern, deep. Best JS tutorial on the
internet. Use for every unit.

MDN Web Docs Authoritative reference. Use for exact [Link]


definitions, API specs, and browser
compatibility.

ECMAScript Spec The actual law of the language. Read [Link]/ecma262


for Under the Hood sections. Not a
tutorial.

V8 Blog How Chrome's JS engine works. [Link]/blog


Engine internals, JIT compilation, GC,
optimizations.

[Link] Docs Official [Link] API documentation. [Link]/docs


Authoritative for all built-in modules.

W3Schools Quick syntax reference and runnable [Link]/js


examples. Good for fast lookup.

[Link] Test and debug regular expressions. [Link]


Shows matches, groups, and
explanation.

[Link]. Visual event loop simulator. Essential [Link]


com for Unit 6 — see the event loop
animate.

[Link] Modern JS and React design patterns. [Link]


Essential for Unit 8.

[Link] Best article on tasks/microtasks. [Link]/2015/tasks-


Required reading for Unit 6. microtasks-queues-and-schedules

[Link]/blog/fast- How V8 optimizes object property [Link]/blog/fast-properties


properties access. Required for Unit 3 Under the
Hood.

[Link]/blog/trash- V8's garbage collector explained. [Link]/blog/trash-talk


talk Required for Unit 8 Under the Hood.

If it exists, it's probably been rewritten in JS. Now go understand why.

You might also like