Why JavaScript.
JavaScript runs everywhere. Browsers (it had no choice, since 1995), Node and its successors (Deno, Bun), Cloudflare Workers and Vercel's edge runtimes, React Native mobile apps, Electron desktop, embedded scripting engines, even as a target for WebAssembly compilation. No other language is deployed in as many places.
The trade: it grew organically. Multiple this-binding rules, coercion surprises, two equality operators, two module systems. Modern JS (ES2015+) makes most of these manageable — but you still need to know the legacy traps to read existing code. The week is about modern JS; the legacy is in the "Common mistakes" section.
The 12 mental models.
Twelve ideas that, once internalised, make the rest of the language read naturally. The fixes for "JS is weird".
- Day-zero
Event loop
Single thread, one queue. Callbacks, promises, microtasks. Why "blocking the main thread" is a thing.
- Day-zero
Closures
Functions remember the variables in scope where they were defined. The lever under every callback, every middleware.
- Day-zero
Prototypes
Objects inherit from objects via the prototype chain. ES6 classes are syntactic sugar over this; the chain is still underneath.
- Day-zero
this binding
Four rules — new, explicit (call/bind), implicit (method call), default. Arrow functions opt out and inherit from enclosing scope.
- Day-zero
Promise
A value that arrives later — or doesn't. .then / .catch / .finally for composition; async/await sugar over it.
- Practitioner
Hoisting
var declarations and function declarations are "hoisted" to the top of scope. let/const are not. Avoid var; the hoisting goes away.
- Day-zero
Truthy / falsy
The 6 falsy values: false, 0, "", null, undefined, NaN. Everything else is truthy. Including empty arrays and empty objects.
- Day-zero
Type coercion
"" == false is true. 0 == "0" is true. Always === . Coercion is a feature; only opt in with explicit Number()/String()/Boolean().
- Practitioner
Destructuring
Const {a, b} = obj. Const [x, y] = arr. The pattern that makes function signatures and assignments terse.
- Practitioner
Iterables
Anything with [Symbol.iterator]. Strings, arrays, sets, maps, generators. for-of works on all of them.
- Practitioner
Modules
import/export (ESM) or require/module.exports (CommonJS). ESM is the modern way; CommonJS still rules legacy Node.
- Runtime
V8 / engine
JIT-compiled. Inline caches, hidden classes, the optimizer (TurboFan), the deoptimizer. Why predictable shapes matter for performance.
Day-zero — the first hour.
- Install Node. nodejs.org — pick latest LTS (v20+). Or use your OS package manager / nvm / fnm.
- Verify.
node --versionandnpm --version. Expect 20.x and 10.x respectively. - Editor. VS Code is the de-facto default for JS — the language server gives you auto-completion and type hints from JSDoc comments without any TS configuration.
- Run JS three ways.
node hello.js, the Node REPL (node), and the browser console (F12). - Sanity-check formatter.
npx prettier --write hello.jsworks without installation.
Day-1 to Day-7.
| Day | Topic | Task |
|---|---|---|
| 1 | Hello, JavaScript | Install Node. node hello.js. Open the REPL. Open browser devtools console. Three ways to run JS. ↗ |
| 2 | Data shapes | Arrays + .map/.filter/.reduce. Objects + destructuring + spread. Build a function that takes ({a, b, ...rest}) and uses them. ↗ |
| 3 | Flow, equality, optional chaining | Internalise === vs ==. Use ?. and ?? . Iterate three ways: for, for-of, .forEach. Pick when each is right. ↗ |
| 4 | Functions, closures, this | Write a function that returns a counter (closure). Test the four `this` rules. Compare arrow vs function. ↗ |
| 5 | Async — promises + await | Chain three promises with .then. Rewrite with async/await. Try Promise.all and Promise.race. ↗ |
| 6 | The platforms | Node: fs.readFile + http.createServer. Browser: document.querySelector + addEventListener. See the same language, different APIs. ↗ |
| 7 | Error handling + idioms | Define a ValidationError subclass. Throw and catch by type. Internalise the ten patterns that distinguish "knows JS" from "writes JS". ↗ |
The full concept walkthrough expands each day to 2–3 deep dives.
Week-1 to Month-3.
Seven tracks for where the next 90 days go. Pick by what your day-job touches.
- Track
TypeScript (separate language)
A separate, typed language that compiles to JS. Worth learning as its own track once you are fluent in JavaScript itself. Useful at API boundaries; not strictly required.
- Track
The browser DOM
document, window, fetch, addEventListener, custom elements, IntersectionObserver. These APIs cover more UI work than most developers realise.
- Track
Node.js
The server-side runtime. fs, http, child_process, streams, the event loop with libuv. The lingua franca of "JS on the server".
- Track
Frontend frameworks
React, Vue, Svelte, Solid. Each picks a different reactivity model. Pick one; understand its rendering model deeply before learning another.
- Track
Bundlers and tooling
Vite for dev, esbuild for speed. webpack for legacy. Browser-targeted vs Node-targeted; ESM vs CJS; the moving target.
- Track
Testing
vitest (modern), jest (the legacy default). Playwright for end-to-end. The fewer mocks, the better the tests.
- Track
Alternative runtimes
Deno (TS-first, secure by default), Bun (JS-first, fast), Cloudflare Workers (V8 isolates). Node is dominant; alternatives are catching up.
The event loop in one paragraph.
JavaScript is single-threaded. Code runs to completion on the main thread.
When a function asks for I/O — fetch, setTimeout,
fs.readFile — the runtime sends the request off and registers a
callback. Control returns to the main thread; the next synchronous code
runs. When the I/O completes, its callback is added to a queue. After every
synchronous call returns, the runtime drains microtasks (promise .then),
then takes one task from the macrotask queue (timers, network), runs it to
completion. Repeat.
This single-threadedness is why "blocking the main thread" is a thing — and why an infinite loop in one browser tab freezes the whole tab. It's also why Node can handle 100k+ concurrent connections on one CPU core: most of the time is spent waiting on I/O, and the loop interleaves them.
Books that matter.
- JavaScript: The Definitive Guide (7th ed) — David Flanagan. The "MDN in book form". Reference-style; not a tutorial.
- You Don't Know JS (series) — Kyle Simpson. Free online. Goes deep on the corners — closures, prototypes, this. The "weird parts" demystified.
- Eloquent JavaScript (4th ed) — Marijn Haverbeke. Free online. The best textbook-style introduction; ramps from zero to interpreters.
- Functional-Light JavaScript — Kyle Simpson. The middle ground between imperative JS and full FP — practical, JS-shaped.
- Node.js Design Patterns (3rd ed) — Mario Casciaro & Luciano Mammino. Where Node-specific idioms live.
- High Performance Browser Networking — Ilya Grigorik. Free online. Not JS-specific, but if you write web apps, every chapter pays off.
Courses & tutorials.
- JavaScript.info — javascript.info. The single best free curriculum. Modern JS, modern style.
- MDN's JavaScript Guide — Mozilla's official reference. developer.mozilla.org
- Frontend Masters' JS path — Will Sentance, Kyle Simpson, Brian Holt. The platform's "Hard parts of JS" series is the canonical intro.
- The Odin Project — free, full-stack curriculum. Heavy hands-on; light on theory. Good if you learn by building.
- Node.js Learn — nodejs.org/learn. Server-side topics — Node-specifics, streams, performance — that the JS-language curricula skip.
Documentation canon.
- MDN Web Docs — developer.mozilla.org. The reference. Bookmark it.
- TC39 proposals — github.com/tc39/proposals. What's coming in JS next.
- Node.js docs — nodejs.org/api. The complete Node API reference.
- V8 blog — v8.dev/blog. Performance internals; how the JIT thinks.
- ECMA-262 spec — the language definition. tc39.es/ecma262. Dense but authoritative.
Talks & videos.
- "What the heck is the event loop anyway?" — Philip Roberts, JSConf EU 2014. Still the best 30 minutes you'll spend on async JS.
- "In the Loop" — Jake Archibald, JSConf Asia 2018. The follow-up: microtasks, tasks, animation frames.
- "Function as a first-class citizen" — Brian Holt, Frontend Masters. The basis for everything functional in JS.
- "V8 internals for JavaScript developers" — Mathias Bynens. How hidden classes, inline caches, and the optimiser actually shape your code's performance.
- Ryan Dahl on Deno — multiple talks. The Node creator's "10 things I regret about Node" plus the case for the next runtime.
JS cheat sheet.
| Command | What it does |
|---|---|
node script.js | Run a single file. |
node | Open the Node REPL. |
npm init -y | Create package.json with defaults. |
npm install <pkg> | Add dependency. --save-dev for devDeps. |
npm install | Install all deps from package.json. |
npm run <script> | Run a script defined in package.json. |
npm test | Run the "test" script. |
npx <binary> | Run a CLI without installing globally. |
npm outdated | Show packages with newer versions available. |
npm audit | Check for known vulnerabilities. |
node --inspect script.js | Run with the Chrome devtools debugger attached. |
npx prettier --write . | Format everything. |
Common mistakes.
- Mistake
Using var
Function-scoped, hoisted, easy to shadow. const by default, let when reassigning. Never var.
- Mistake
Using ==
Coercion is hard to predict. Always ===. The two exceptions: foo == null catches both null and undefined (sometimes useful).
- Mistake
Floating point math
0.1 + 0.2 !== 0.3. JS uses IEEE 754 like most languages. For money: use integers (cents) or decimal.js.
- Mistake
this in callbacks
setTimeout(this.method, 100) loses `this`. Use an arrow function: setTimeout(() => this.method(), 100).
- Mistake
Forgetting await
asyncFn() returns a promise. Without await, the next line runs before the promise resolves. ESLint catches this if you ask.
- Mistake
Mutating props in React
React expects immutability. Mutating arrays/objects in state silently breaks renders. Spread, slice, or use immer.
Semicolony assets.
- Computer networking — what fetch() runs on top of.
- System design — JS-backed services share the same patterns.
- Go — the comparison point for "modern backend without GC drama".
- Rust — for when you need WASM and want types you can trust.
- API design — REST and GraphQL, the two protocols JS most often serves.
Roadmap — when ready.
- Week 1. JavaScript.info chapters 1-10 + the seven-day plan above. Read modern JS fluently.
- Month 1. Build a CLI in Node (use commander) AND a single-page app in React/Svelte. Cover both runtimes.
- Month 2. Read the V8 internals — hidden classes, inline caches, the optimiser. Profile a hot path with the inspector and learn what your code costs.
- Month 3. Pick a specialism — a frontend framework (React/Svelte/Vue), an alternative runtime (Bun, Deno), or backend Node at scale with Fastify or NestJS.
- Year 1. Contribute to a major OSS JS project. Read V8 blog posts monthly. If you want types, treat TypeScript as a separate track and learn it properly.
Keep going.
JavaScript rewards persistence. The first month, the language fights you with
coercion and this. By month three you're shipping modern JS,
async/await flows naturally, and you can debug a missing await
on a stack trace. By year one, modern JS is the most productive scripting
experience available — and you can pick up TypeScript as a separate track
if your project needs static types.