The modern JavaScript course
Learn JavaScript, the illustrated way.
From your first line of code to prototypes, closures, and the event loop — explained with diagrams and interactive animations, one concept at a time.
Part 1
JavaScript Fundamentals
Getting Started
- An Introduction to JavaScriptWhat JavaScript is, where it runs, what it can and can't do in a browser, and why it stayed the default language of the web.
- Manuals and specificationsWhere to look things up once you outgrow a tutorial: the ECMAScript spec, MDN, and the compatibility tables that tell you what actually runs where.
- Code editorsHow code editors split into full IDEs and fast lightweight editors, when to reach for each, and how to pick one without getting stuck.
- Developer consoleHow to open the browser's developer tools, read the errors it shows, and run JavaScript straight from the console.
First Steps
- Hello, world!How to attach JavaScript to a web page with the <script> tag: inline code, external files via src, and the attributes you can safely ignore.
- Code structureHow JavaScript is built from statements, why semicolons matter more than they look, and how to comment code without breaking it.
- The modern mode, "use strict"What "use strict" does, why it exists, where it must go, and when modern classes/modules make it automatic.
- VariablesHow to store data in named variables with let and const: declaring, assigning, reassigning, copying, naming, and why const communicates intent.
- Data typesThe eight data types JavaScript can store (number, bigint, string, boolean, null, undefined, symbol, object), and how to tell them apart with typeof.
- Interaction: alert, prompt, confirmHow the browser's three built-in dialogs (alert, prompt, and confirm) let a script talk to a person, what each one returns, and why they freeze the page.
- Type ConversionsHow JavaScript turns values into strings, numbers, and booleans: the automatic conversions you rarely notice and the explicit ones you control.
- Basic operators, mathsHow JavaScript's arithmetic, string, unary, assignment, increment, bitwise, and comma operators behave, plus the precedence rules that decide what runs first.
- ComparisonsHow JavaScript compares values: booleans as results, lexicographic string order, type coercion in loose equality, strict equality, and the null/undefined traps.
- Conditional branching: if, '?'How to branch your code with if, else, else if, and the ternary ? operator, plus the truthy/falsy rules that decide which branch runs.
- Logical operatorsHow ||, &&, and ! actually work in JavaScript: value-returning short-circuit evaluation, not plain true/false.
- Nullish coalescing operator '??'The ?? operator returns the first value that isn't null or undefined: how it works, why it beats || for defaults, and the precedence traps to watch for.
- Loops: while and forHow to repeat work in JavaScript with while, do..while, and for, plus break, continue, and labels for escaping nested loops.
- The "switch" statementHow switch compares one value against many candidates with strict equality, why break matters, and how fall-through lets you group cases.
- FunctionsHow to declare functions, pass arguments, use default parameters, return values, and name them so the code reads like prose.
- Function expressionsA function in JavaScript is a value you can store, copy, and pass around. Where you write it decides whether it exists before the code runs or only once execution reaches it.
- Arrow functions, the basicsArrow functions give you a compact syntax for writing functions, with an implicit return for one-liners and curly braces when you need a full body.
- JavaScript specialsA fast, connected recap of the First Steps chapter: code structure, strict mode, variables, interaction, operators, loops, switch, and functions, with the subtle gotchas pulled to the front.
Code Quality
- Debugging in the browserUse the browser's Sources panel (breakpoints, the debugger statement, the Scope/Call Stack/Watch panes, and step-by-step tracing) to see exactly what your code does while it runs.
- Coding stylePractical style conventions (braces, line length, indentation, semicolons, nesting, function placement, style guides, and linters) that make JavaScript readable and less error-prone.
- CommentsHow to comment well: strip out comments that narrate what the code does, keep the ones that explain architecture, function usage, and the reasons behind a design.
- Ninja codeA tongue-in-cheek tour of code-obfuscation 'tricks' that teaches, by inversion, exactly which habits make code unreadable, and what to do instead.
- Automated testing with MochaLearn Behavior Driven Development by building a multiply function test-first with Mocha, Chai, describe/it blocks, nested groups, and setup hooks.
- Polyfills and transpilersHow transpilers rewrite modern syntax for old engines and polyfills add missing built-in functions, so you can write current code that still runs everywhere.
Object Basics
- ObjectsObjects store keyed collections of data: how to create them, read and write properties with dot and bracket notation, use computed keys and shorthands, test for existence with in, and iterate with for..in.
- Object references and copyingObjects are held and copied by reference while primitives copy as whole values, which shapes how equality, cloning, and nested data behave.
- Garbage collectionHow JavaScript automatically frees memory by tracking which values are still reachable from the roots, and how the mark-and-sweep collector works under the hood.
- Object methods, "this"How to give objects behavior with methods, and how the value of `this` is decided at call-time by whatever sits before the dot.
- Constructor, operator "new"How constructor functions plus the new operator let you stamp out many similar objects from one blueprint.
- Optional chaining '?.'Use ?. to read, call, and delete through nested values that might be null or undefined without crashing.
- Symbol typeSymbols are guaranteed-unique primitive keys used for collision-free hidden object properties and for hooking into JavaScript's built-in behaviors through well-known symbols.
- Object to primitive conversionHow JavaScript turns an object into a string or number when an operator demands a primitive, and the three methods you can define to control it.
Part 2
Types, Functions & Classes
Data Types
- Methods of primitivesPrimitives stay lightweight, yet you can call methods on strings, numbers, booleans, symbols, and bigints because JavaScript wraps them in a temporary object just long enough to run the call.
- NumbersEverything about regular JavaScript numbers: exponential and alternate-base syntax, rounding, the IEEE-754 precision trap, NaN/Infinity tests, and parsing numbers out of strings.
- StringsHow JavaScript stores text as UTF-16 strings, and the full toolkit for quoting, indexing, slicing, searching, and comparing them.
- ArraysHow JavaScript arrays really work: zero-based indexing and at(), the push/pop/shift/unshift toolbox, the object underneath, performance, looping, the writable length, and why you never compare arrays with ==.
- Array methodsA tour of the array toolbox (adding, removing, searching, iterating, and transforming) with the mental models behind splice, map, filter, sort, and reduce.
- IterablesHow for..of really works: the Symbol.iterator protocol, writing your own iterators, the iterable vs array-like distinction, and Array.from to bridge them.
- Map and SetMap stores keyed data with keys of any type, and Set stores unique values. Both remember insertion order and beat plain objects and arrays at their respective jobs.
- WeakMap and WeakSetWeakMap and WeakSet hold objects with weak references, so a key or member vanishes automatically once nothing else points to it.
- Object.keys, values, entriesHow to pull keys, values, and key/value pairs out of plain objects, and how to borrow array methods to transform an object into a new one.
- Destructuring assignmentUnpack arrays and objects into individual variables with defaults, renaming, rest patterns, nesting, and clean function parameters.
- Date and timeHow the built-in Date object stores time as a millisecond timestamp, how to read and set its components, why months count from zero, autocorrection, date diffs, and honest benchmarking.
- JSON methods, toJSONHow JSON.stringify and JSON.parse turn objects into portable text and back, plus the hooks (replacer, space, toJSON, and reviver) that let you shape the result.
Advanced Functions
- Recursion and stackHow a function that calls itself actually runs: the base case and recursive step, the execution-context stack that powers it, and the recursive data structures (trees, linked lists) that recursion was made for.
- Rest parameters and spread syntaxGather any number of arguments into an array with rest parameters, and expand an iterable into a list with spread syntax (plus copying arrays and objects).
- Variable scope, closureEvery JavaScript function permanently remembers the scope it was born in, and that single rule (closure) explains how counters keep state, how variables stay alive after a function returns, and when memory gets freed.
- The old "var"How var differs from let and const: no block scope, tolerant redeclarations, and hoisting, plus the IIFE trick that older code used to fake privacy.
- Global objectThe global object collects the built-in and environment-provided values available everywhere, reachable through window, global, or the portable globalThis.
- Function object, NFEFunctions are callable objects: read their name and length, hang your own properties on them, and use a named function expression to reference a function reliably from inside itself.
- The "new Function" syntaxHow new Function builds a function from a string at run time, and why its scope is deliberately global instead of the surrounding one.
- Scheduling: setTimeout and setIntervalHow to defer and repeat function calls with setTimeout and setInterval, cancel them, and control timing precisely with nested timeouts.
- Decorators and forwarding, call/applyHow to wrap a function in another function that adds behavior (caching, logging, timing) using call, apply, and call forwarding without touching the original code.
- Function bindingWhy methods forget their object when passed around as callbacks, and how bind pins this (and arguments) in place.
- Arrow functions revisitedArrow functions have no this, no arguments, no super, and can't be called with new, which makes them ideal for small callbacks that borrow their surrounding context.
Object Properties
- Property flags and descriptorsEvery object property carries three hidden flags (writable, enumerable, configurable), and this lesson shows how to read them, change them, and lock an object down entirely.
- Property getters and settersHow accessor properties let a getter and setter run behind a plain-looking property read or write, and why that indirection is so useful for validation and refactoring.
Prototypes
- Prototypal inheritanceHow objects in JavaScript quietly fall back to a linked prototype object when a property is missing, and the rules that govern that lookup.
- F.prototypeHow the prototype property on a constructor function decides the [[Prototype]] of every object it builds with new.
- Native prototypesHow JavaScript's built-in objects store their methods on shared prototypes, and when it is safe to touch those prototypes yourself.
- Prototype methods, objects without __proto__The modern ways to read and set a prototype without __proto__, plus how prototype-less objects give you a safe dictionary for user-supplied keys.
Classes
- Class basic syntaxHow the class keyword builds a constructor function plus prototype methods, and what it adds on top: strict mode, non-enumerable methods, getters/setters, computed names, and class fields.
- Class inheritanceHow one class extends another with `extends`, how `super` calls parent methods and constructors, and the prototype and [[HomeObject]] machinery that makes it all work.
- Static properties and methodsHow static methods and properties attach to the class itself rather than its instances, why factory and comparison methods live there, and how statics are inherited through the class prototype chain.
- Private and protected properties and methodsHow to split an object into a public interface and hidden internals using protected `_` conventions and language-enforced private `#` fields.
- Extending built-in classesYou can extend built-ins like Array and Map with your own methods, control what their methods return using Symbol.species, and understand why built-in classes don't inherit each other's static methods.
- Class checking: "instanceof"How `instanceof` walks the prototype chain to test class membership (including inheritance), how to override it with `Symbol.hasInstance`, and how `Object.prototype.toString` acts as a typeof on steroids.
- MixinsHow to bolt reusable behavior onto a class in JavaScript by copying methods into a prototype, since a class can only extend one parent.
Part 3
Async, Modules & Modern JavaScript
Error Handling
- Error handling, "try...catch"How try...catch intercepts runtime errors, how the error object and throw work, and the rethrowing and finally patterns that keep error handling honest.
- Custom errors, extending ErrorBuild your own error classes by extending Error, organize them into a hierarchy, check them with instanceof, and wrap low-level failures into higher-level errors.
Async
- Introduction: callbacksHow callback-based asynchronous code works, how to report errors with error-first callbacks, and why deeply nested callbacks turn into the pyramid of doom.
- PromiseHow a promise links producing code to consuming code through its pending/fulfilled/rejected state, and how then, catch, and finally subscribe to the outcome.
- Promises chainingHow to run asynchronous steps in sequence by returning values and promises from .then handlers, building a flat chain instead of nested callbacks.
- Error handling with promisesHow rejections travel down a promise chain to the nearest .catch, why handlers get an invisible try..catch, how to rethrow, and how to trap unhandled rejections.
- Promise APIThe six static Promise methods (all, allSettled, race, any, resolve, reject) and exactly when to reach for each.
- PromisificationHow to wrap a callback-based function so it returns a promise instead, plus a reusable promisify helper that handles error-first callbacks with one or many result arguments.
- MicrotasksWhy promise handlers always run after the current code finishes, how the microtask queue schedules them, and how that timing explains unhandled-rejection detection.
- Async/awaitHow the async and await keywords let you write promise-based code that reads top to bottom, plus error handling with try..catch and the edge cases worth knowing.
Generators Iterators
- GeneratorsHow generator functions pause and resume with yield, act as iterables, compose with yield*, and exchange values and errors with the calling code.
- Async iteration and generatorsIterate over data that arrives over time using Symbol.asyncIterator, async generators, and for await..of, with a real paginated-fetch example.
Modules
- Modules, introductionModules let you split a program across files that share functionality through export and import, each with its own scope, strict mode, and one-time evaluation.
- Export and ImportA tour of every export and import form: inline and standalone exports, renaming with as, default exports, re-exports, and where these statements are allowed to live.
- Dynamic importsLoad modules on demand with the import() expression, which returns a promise for the module object and works from anywhere in your code.
JavaScript Misc
- Proxy and ReflectHow a Proxy wraps an object and intercepts fundamental operations like reads, writes, and function calls, and how Reflect lets each trap forward the operation faithfully.
- Eval: run a code stringeval runs a string as live JavaScript, returns the last statement's value, and (in a way that's usually best avoided) can read and write the surrounding scope.
- CurryingTurning f(a, b, c) into f(a)(b)(c) so you can lock in arguments early and spin off tidy specialized functions.
- Reference TypeThe dot operator returns a hidden Reference Type value that carries this into the call. Pull the method off first and this evaporates.
- BigIntBigInt is a numeric type for integers of any size, created with an n suffix or the BigInt() function, that behaves like a number but never mixes with one silently.
- Unicode, String internalsJavaScript strings are UTF-16, so rare characters take two code units (surrogate pairs) and visually identical letters can differ byte-for-byte until you normalize them.
- WeakRef and FinalizationRegistryHow WeakRef holds an object without keeping it alive, and how FinalizationRegistry runs a callback after the garbage collector reclaims it.
Modern Collections
- Immutable Array MethodsThe non-mutating twins of sort, reverse, and splice (toSorted, toReversed, toSpliced, with), plus findLast and findLastIndex, and why returning a fresh copy makes state predictable.
- Grouping with Object.groupBy & Map.groupBySort any iterable into buckets by a computed key in one call (Object.groupBy for string keys, Map.groupBy for object keys) and retire the hand-rolled reduce boilerplate.
- Set MethodsThe built-in Set now speaks set algebra directly. Union, intersection, difference, symmetricDifference, and three containment checks mean you can drop the hand-rolled loops and the Lodash helpers.
- Iterator HelpersChainable map, filter, take, drop and friends that live on Iterator.prototype and pull one value at a time: lazy pipelines that never build intermediate arrays and can bound an infinite generator.
- Array.fromAsyncBuild an array from an async iterable or an iterable of promises, awaiting each element in sequence: the clean way to drain an async generator or paginate an API into one list.
Async Upgrades
- Promise.withResolversOne call hands you a promise plus its resolve and reject functions, so you can settle a promise from outside its constructor without the old outer-variable dance.
- Error Cause & AggregateErrorChain errors with the cause option so a boundary can add context without losing the root failure, and bundle many failures into one AggregateError the way Promise.any does.
Language Extras
- Logical Assignment, Object.hasOwn & structuredCloneThree sharp modern tools: the ??=, ||= and &&= assignment operators, Object.hasOwn for safe key checks, and structuredClone for real deep copies.
- Decorators & Static Initialization BlocksHow Stage 3 class decorators wrap classes, methods, fields, and accessors through a (value, context) contract that still needs a build step, and how ES2022 static blocks run one-time setup at class definition.
- RegExp v and d FlagsTwo modern regex flags: v upgrades character classes with real set algebra and multi-character string sets, and d reports the exact start and end index of every match and capture group.
Internationalization
Part 4
The Browser Platform
Document
- Browser environment, specsThe browser wraps the JavaScript language core with a host environment (window, the DOM, and the BOM), each governed by its own specification.
- DOM treeHow the browser turns HTML into a live tree of node objects that JavaScript can read and change.
- Walking the DOMHow to move between DOM nodes using navigation properties for parents, children, and siblings, plus element-only shortcuts and table-specific links.
- Searching: getElement*, querySelector*How to reach any element on a page by id, CSS selector, tag, class, or name, plus matches, closest, and the difference between live and static collections.
- Node properties: type, tag and contentsEvery DOM node is a JavaScript object from a class hierarchy, and this chapter maps the classes and the everyday properties for reading a node's type, tag, and contents.
- Attributes and propertiesHTML attributes and DOM properties look like two names for the same thing, but they live in different places, carry different types, and sync in ways that trip people up. This chapter untangles them.
- Modifying the documentCreate, insert, move, clone, and remove DOM nodes to build live, dynamic pages.
- Styles and classesJavaScript can reach an element's look two ways: through its CSS classes or through inline styles. Knowing which to reach for (and how to read the value back) keeps your UI code clean.
- Element size and scrollingHow to read an element's width, height, borders, padding, and scroll offsets in pixels using the offset/client/scroll geometry properties, and why CSS values are the wrong tool for the job.
- Window sizes and scrollingHow to read the window's visible size, the full document height, and the current scroll position, plus the methods that move the page, and the historical quirks that make you take a Math.max of six properties.
- CoordinatesThe two coordinate systems on a web page (window-relative and document-relative), how getBoundingClientRect reports them, and how to convert between them so a tooltip stays glued to its element whether the page scrolls or not.
Events
- Introduction to browser eventsHow the browser turns user actions into events, and the three ways to attach handler code that reacts to them.
- Bubbling and capturingAn event on an element travels down through its ancestors and back up through them, and understanding that journey is what lets one handler serve a whole subtree.
- Event delegationInstead of wiring a handler onto every element, put one handler on a shared ancestor and let bubbling bring the events to you.
- Browser default actionsHow the browser reacts to events on its own, and how to cancel that behavior with preventDefault, return false, passive handlers, and defaultPrevented.
- Dispatching custom eventsCreate and fire your own events from JavaScript with Event, CustomEvent, and dispatchEvent, pass data via detail, cancel with preventDefault, and understand why nested events run synchronously.
Event Details
- Mouse eventsThe mouse event family: their fixed firing order, the button and modifier-key properties every event carries, the two coordinate systems, and how to stop mousedown from selecting text.
- Moving the mouse: mouseover/out, mouseenter/leaveHow mouseover/out, mousemove, and mouseenter/leave differ, why bubbling and relatedTarget matter, and how to delegate hover handling across many elements.
- Drag'n'Drop with mouse eventsBuild drag'n'drop from scratch with mousedown/mousemove/mouseup, keep the pointer's grab offset, and detect drop targets under the cursor with elementFromPoint.
- Pointer eventsOne unified event model that handles mouse, touch, and pen input, with multi-touch, device pressure, and pointer capturing built in.
- Keyboard: keydown and keyupHow keydown and keyup work, the difference between event.key and event.code, auto-repeat, default actions, and why keyboard events alone can't reliably track text input.
- ScrollingThe scroll event lets you react to page and element scrolling, why you can't cancel it after the fact, and how to block scrolling at its real source instead.
Forms Controls
- Form properties and methodsHow to reach forms and their controls through document.forms and form.elements, and how to read and set values on input, textarea, select, and option.
- Focusing: focus/blurHow elements gain and lose focus, why the focus and blur events behave differently from most others, and how tabindex, capturing, and focusin/focusout let you work around their quirks.
- Events: change, input, cut, copy, pasteThe events that fire when form data changes: change on commit, input on every keystroke or paste, and the clipboard trio cut/copy/paste, plus why the clipboard sits behind a wall of safety restrictions.
- Forms: event and method submitHow the submit event lets you validate or cancel a form before it leaves the page, and how form.submit() sends a form from code without firing that event.
Loading
- Page: DOMContentLoaded, load, beforeunload, unloadHow a page's lifecycle unfolds through DOMContentLoaded, load, beforeunload, and unload, and how to hook into each stage reliably.
- Scripts: async, deferHow defer and async change when the browser downloads and runs your scripts, and how to pick the right one.
- Resource loading: onload and onerrorHow to know when a script, image, or other external resource finishes loading or fails, and how cross-origin rules limit what errors you can see.
UI Misc
- Mutation observerMutationObserver watches a DOM node and fires a callback whenever its children, attributes, or text change. Ideal for reacting to markup you don't control.
- Selection and RangeHow Range marks a pair of boundary points in the DOM, how Selection turns ranges into a visible highlight, and the simpler text-only selection API for input and textarea.
- Event loop: microtasks and macrotasksHow the browser (and Node.js) schedules your code: the endless task loop, why rendering waits for your task to finish, and the strict order in which macrotasks and microtasks run.
Native UI
- Native Dialogs & the Popover APIBuild modals, menus, and popovers with the platform's own top-layer primitives (the dialog element and the Popover API) instead of hand-rolling overlays, z-index stacks, and focus traps.
- The View Transitions APIAnimate DOM state changes and page navigations natively. The browser snapshots the old and new states and cross-fades or morphs between them, so you delete your FLIP and clone-node code.
- The Web Animations APIDrive animations from JavaScript with element.animate: a real Animation object you can play, pause, reverse, seek, rescale in speed, and await, plus a look at scroll-driven timelines.
- The Navigation APIA single navigate event that catches every same-origin navigation (links, back/forward, and programmatic calls), plus intercept() to render it yourself without a full page load.
Input and Devices
- Clipboard & Native Drag-and-DropCopy and paste with the async Clipboard API (text, rich HTML, and images through the permission gate), then move data with native HTML5 drag-and-drop, from the draggable attribute to DataTransfer and the dragover preventDefault trick.
- Device & Capability APIsHow to ask the browser for powerful capabilities the respectful way: checking permission state first, gating on a real user gesture, feature-detecting before you call, and scheduling non-urgent work for idle time.
Part 5
Advanced Web Platform
Frames and Windows
- Popups and window methodsHow to open, control, close, move, and communicate with popup windows using window.open and the related window methods, plus the browser rules that limit what you can do.
- Cross-window communicationHow the Same Origin policy walls off windows and frames from each other, and the sanctioned escape hatches — document.domain, sandbox, and postMessage.
Web Security
- The clickjacking attackHow clickjacking tricks a user into clicking a hidden victim button, and the layered defenses — framebusting, sandbox, X-Frame-Options, covering divs, and SameSite cookies — that stop it.
- Web Security in DepthA production-grade tour of browser security: XSS and its defenses, Content Security Policy, Trusted Types, CSRF, Subresource Integrity, CORS at the trust level, and modern auth with passkeys and OAuth2.
Binary Data and Files
- ArrayBuffer, binary arraysHow JavaScript models raw bytes: ArrayBuffer as the memory, typed arrays and DataView as the views that interpret it.
- TextDecoder and TextEncoderTurn raw bytes into JavaScript strings with TextDecoder, and strings back into UTF-8 bytes with TextEncoder.
- BlobBlob is binary data with a type attached — the object the browser uses for downloads, uploads, images, and object URLs.
- File and FileReaderA File is a Blob with a name and modification date, and FileReader pulls its contents into a string, ArrayBuffer, or data URL through events.
Network Requests
- Fetchfetch() sends a network request and hands back a promise that resolves in two stages — first the response headers, then the body you read with a second method call.
- FormDataUse the FormData object to capture form fields, files, and Blobs, then POST them with fetch as multipart/form-data.
- Fetch: Download progressRead a fetch response chunk-by-chunk through response.body to track how many bytes have downloaded and show real progress.
- Fetch: AbortUse AbortController to cancel an in-flight fetch (or any async task) by wiring its signal into fetch and calling abort() when the work is no longer needed.
- Fetch: Cross-Origin RequestsHow the browser guards cross-origin fetch requests with CORS — origins, safe requests, preflight, response headers, and credentials.
- Fetch APIA tour of every fetch option beyond method/headers/body — referrer, mode, credentials, cache, redirect, integrity, keepalive — with what each one controls and when you'd reach for it.
- URL objectsUse the built-in URL class to build, parse, and safely encode web addresses instead of juggling raw strings.
- XMLHttpRequestXMLHttpRequest is the older browser API for HTTP requests — event-driven, capable of tracking upload progress, and still worth knowing where fetch falls short.
- Resumable file uploadBuild resumable file uploads by asking the server how many bytes it already has, then slicing the file and sending only the rest.
Realtime and Streaming
- Long pollingLong polling keeps a persistent link to the server by holding each request open until a message is ready, giving you near-instant delivery with plain HTTP and no special protocol.
- WebSocketHow WebSocket opens a persistent two-way channel between browser and server, from the HTTP handshake to frames, backpressure, close codes, and a working chat.
- Server Sent EventsEventSource opens a persistent HTTP connection so the server can stream text events to the browser, with built-in auto-reconnect, message ids, and custom event types.
- The Streams APIProcess data piece by piece with readable, writable, and transform streams — reading chunk by chunk, piping through processing chains, and letting a slow consumer push back on a fast producer.
- WebRTC & WebTransportTwo low-latency transports beyond WebSocket: WebRTC for peer-to-peer media and data with NAT traversal, and WebTransport for multiplexed client-server messaging over HTTP/3.
Concurrency and Workers
- Web WorkersHow Web Workers run JavaScript on a real background thread, communicate through postMessage, copy data with structured clone, and hand off buffers with zero-copy transferables.
- SharedArrayBuffer & AtomicsHow SharedArrayBuffer lets multiple threads read and write the same memory, why it needs cross-origin isolation, and how Atomics gives you race-free updates and wait/notify coordination.
- Service Workers & PWAsHow a service worker acts as a programmable network proxy to make web apps installable and offline-first, covering the lifecycle, the Cache API and caching strategies, the manifest, and a look at Background Sync and Push.
Browser Storage
- Cookies, document.cookieHow cookies flow between server and browser, how to read and write them with document.cookie, and what each attribute (domain, path, expires, secure, samesite, httpOnly) actually controls.
- LocalStorage, sessionStorageHow localStorage and sessionStorage keep key/value strings in the browser, how their scope and lifetime differ, and how the storage event lets same-origin windows talk to each other.
- IndexedDBA deep, example-driven tour of IndexedDB: opening and versioning databases, object stores, transactions, indexes, cursors, and a promise wrapper for clean async code.
Animation
- Bezier curveBezier curves are shapes defined by control points; De Casteljau's algorithm builds them by repeated linear interpolation, and a matching polynomial formula describes the same curve.
- CSS-animationsAnimate CSS properties with transitions, timing functions, steps, and @keyframes, then hook into transitionend and lean on transform/opacity for smooth performance.
- JavaScript animationsBuild smooth, fully controllable JavaScript animations with requestAnimationFrame, a reusable animate() helper, and a toolbox of timing functions plus easeIn/Out/InOut transforms.
Web Components
- From the orbital heightA high-level tour of why component architecture matters and which browser standards make up web components.
- Custom elementsDefine your own HTML tags with a JavaScript class, hook into their lifecycle callbacks, react to attribute changes, and extend built-in elements.
- Shadow DOMGive a component its own private DOM tree with scoped styles and its own id space, isolated from the surrounding page.
- Template elementThe <template> element is an inert, syntax-checked container for HTML you clone and inject later — perfect for reusable component markup.
- Shadow DOM slots, compositionHow Shadow DOM slots pull light-DOM content into a component's shadow tree via composition, producing a virtual flattened DOM without moving any nodes.
- Shadow DOM stylingHow CSS crosses (or doesn't cross) the shadow boundary — :host, ::slotted, cascading rules, and custom properties as styling hooks.
- Shadow DOM and eventsHow the browser retargets events at shadow DOM boundaries, how composedPath and the composed flag control what crosses those boundaries, and how to fire custom events that escape a component.
Regular Expressions
- Patterns and flagsHow to build regular expressions in JavaScript with the two syntaxes, what each of the six flags does, and how str.match, str.replace, and regexp.test use them to search, replace, and test text.
- Character classesHow regex character classes like \d, \s, \w and their inverses match whole categories of characters, plus how the dot and the s flag behave.
- Unicode: flag "u" and class \p{...}How the u flag makes regular expressions treat 4-byte characters as one and unlocks Unicode property classes like \p{L}.
- Anchors: string start ^ and end $The ^ and $ anchors pin a pattern to the start or end of a string, and together they let you demand a full, exact match.
- Multiline mode of anchors ^ $, flag "m"The m flag turns ^ and $ into per-line anchors, matching at every line break instead of only at the string boundaries.
- Word boundary: \bLearn how the \b word boundary anchor matches the invisible edges between word and non-word characters, and where it falls short.
- Escaping, special charactersHow to match special regexp characters literally by escaping them, why /.../ and new RegExp differ, and why string-based patterns need doubled backslashes.
- Sets and ranges [...]How square brackets in a regexp let one position match any character from a set, a range, or a character class — plus exclusions, escaping rules, and the u flag for astral characters.
- Quantifiers +, *, ? and {n}Quantifiers control how many times a pattern repeats — from the exact {n} form to the everyday shorthands +, * and ?.
- Greedy and lazy quantifiersHow quantifiers backtrack in greedy mode, how the lazy mode flips that behavior, and why a fine-tuned character exclusion sometimes beats both.
- Capturing groupsHow parentheses in a regexp group sub-patterns, capture matched text, and expose it by number or name in match, matchAll, and replace.
- Backreferences in pattern: \N and \k<name>Reuse what a capturing group already matched — by number with \N or by name with \k<name> — to match balanced quotes and other repeated text.
- Alternation (OR) |The regexp | operator lets you match any one of several full sub-patterns, and parentheses control exactly how far its reach extends.
- Lookahead and lookbehindMatch text based on what comes before or after it — without consuming those surrounding characters — using lookahead and lookbehind assertions.
- Catastrophic backtrackingSome innocent-looking regexps blow up to exponential work on certain inputs, and you fix it either by removing ambiguity or by forbidding the engine from backtracking.
- Sticky flag "y", searching at positionThe sticky flag y anchors a regexp to an exact position via lastIndex, so exec matches only there and never scans ahead.
- Methods of RegExp and StringA tour of every string and regexp method for searching and replacing — match, matchAll, split, search, replace, replaceAll, exec, and test — with their traps around the g flag and lastIndex.
Graphics and Media
- Canvas, WebGL & WebGPUDraw with pixels instead of elements: the Canvas 2D immediate-mode model and render loop, the GPU pipeline behind WebGL, the emerging WebGPU compute-and-render API, and moving rendering off the main thread with OffscreenCanvas.
- Web Audio & WebCodecsSynthesize and shape sound with the Web Audio node graph, then reach the browser's built-in video and audio codecs directly through WebCodecs for custom media pipelines.
- WebAssemblyWhat WebAssembly is and why it exists: a compact sandboxed bytecode that runs beside JavaScript at near-native speed, its module/instance/memory model, the cost of crossing the JS boundary, how to load it with instantiateStreaming, and which toolchain compiles C, Rust, or AssemblyScript down to a .wasm.
Part 6
Ecosystem & Tooling
Packages and Publishing
- Modules, npm & Semantic VersioningHow real projects are wired together: ES modules at the ecosystem level, the anatomy of package.json, npm versus pnpm and what a lockfile guarantees, semantic versioning ranges, the exports field, and supply-chain hygiene.
- Package Managers in Depth: npm, pnpm, Yarn & BunHow npm, pnpm, Yarn and Bun actually resolve and lay out dependencies on disk — flat hoisting versus a content-addressed store, the phantom-dependency trap, lockfiles and frozen installs, and how to pick one in 2026.
- Publishing a Package: exports, Provenance & JSRHow to take code from a repo to a registry: the publisher side of package.json, the exports map, why ESM-only is winning, previewing the tarball, provenance via trusted publishing from CI, and when JSR beats npm.
- Monorepos & Workspaces: pnpm, Turborepo & NxOne repo with many packages: linking local packages with workspaces, skipping unchanged work with Turborepo's content-aware cache, scaling to Nx, wiring TypeScript project references, and publishing with Changesets.
- Supply-Chain Security: Trusting Your DependenciesHow to stay safe in an ecosystem where malicious packages are industrialized: lockfiles, cooldowns, install-script blocking, scoped short-lived tokens, provenance, SBOMs, and a practical way to vet a new dependency.
Compiling and Bundling
- Build Tools: Vite, esbuild & RolldownWhy a bundler exists, how Vite serves native ES modules in development and ships optimized chunks in production, and how tree-shaking, code-splitting, minification and source maps turn a folder of modules into a few small hashed files.
- Transpilers & the Compile Pipeline: Babel, SWC, esbuild & tscHow a transpiler turns source into an AST and back, why down-leveling syntax is different from polyfilling a missing API, and what Babel, SWC, esbuild and tsc each actually do in a 2026 toolchain.
- TypeScript Tooling: tsconfig, Project References & TS 7How TypeScript's tooling actually works in 2026 — splitting type-checking from emit, writing a tsconfig that matches your project, cutting big type-checks with project references, running .ts files directly, and what the Go-native TypeScript 7 compiler changes.
Quality and Automation
- Code Quality: ESLint, Prettier & BiomeHow linting and formatting split the job of keeping a codebase clean — ESLint's flat config and typed rules for likely bugs, Prettier for opinionated style, Biome as a fast Rust all-in-one, and how to enforce them on save, on commit, and in CI.
- Testing: Vitest & PlaywrightA modern JavaScript testing stack — the testing pyramid, fast unit tests and mocking with Vitest, behavior-first component tests with Testing Library, real-browser end-to-end flows with Playwright, and how to keep it all deterministic and green in CI.
- Git Hooks & Pre-Commit Quality GatesHow git hooks catch broken code and malformed commit messages before they land — pre-commit, commit-msg and pre-push stages driven by husky or lefthook, lint-staged keeping commits fast, commitlint enforcing Conventional Commits, and why CI still has to back all of it up.
- CI/CD with GitHub ActionsHow JavaScript projects ship automatically — GitHub Actions workflows, jobs and runners, dependency caching, matrix builds, secrets and environments, and automated releases with Changesets and semantic-release publishing over OIDC.
Runtimes and Deployment
- Node.js, Deno & BunHow JavaScript runs on the server: the Node runtime built on V8 and libuv, its event loop and core modules, CommonJS versus ESM, native TypeScript in 2026, and how Deno and Bun compare on permissions, tooling, and speed.
- Edge & Serverless Runtimes: Workers, Vercel & WinterTCHow JavaScript runs close to your users: serverless functions versus long-running servers, V8 isolates and sub-5ms cold starts, the WinterTC web-standard API surface shared across Node, Deno, Bun and Workers, and Hono as the cross-runtime framework that ties them together.
- Deploying a JavaScript AppA practical walkthrough of shipping a JavaScript app to production: choosing between static, serverless, container, and VPS hosting; the build-to-artifact-to-CDN flow; handling env vars and secrets safely; cache-control headers; and wiring up a custom domain with TLS.
Frameworks and Rendering
- How Frameworks Work: Reactivity, Signals & the Virtual DOMThe single problem every UI framework solves — keeping the DOM in sync with your state — and the three strategies used to do it: virtual DOM diffing, fine-grained signals, and compilers that ship surgical DOM code.
- Rendering Models: CSR, SSR, SSG, ISR, Streaming & IslandsWhere and when your HTML gets produced — at build time, per request on the server, or in the browser — and the concrete tradeoffs each choice makes for first paint, interactivity, SEO, and server cost.
- Meta-Frameworks: Next.js, Astro, SvelteKit & RemixWhat a meta-framework layers on top of a UI library — routing, data fetching, rendering, bundling, and deploy adapters — and a practical way to pick between Next.js, Astro, SvelteKit, and Remix for a given project.
Part 7
Server-Side JavaScript
Server Foundations
- How an HTTP Server Actually WorksA server is a process that binds a port and trades agreed-upon text over a socket. Here is what HTTP looks like on the wire, and why res.end matters.
- Reading a Request: Headers, Bodies and Why Parsing Is HardThe headers are already parsed when your handler runs. The body is not even there yet. That gap explains body parsers, charset bugs and size limits.
- Streaming a Response, and BackpressureWhy buffering a big response kills the process, what backpressure actually is, and why pipeline beats pipe when something fails halfway through.
- Routing From Scratch, and What a Framework AddsRouting is a lookup from method plus path to a handler. Build one, meet the precedence trap, and see why fast routers use a tree.
- Middleware: The Onion ModelThe rest of your app, packed into one function you choose to call. How the chain runs, why order decides everything, and what next actually returns.
- One Thread, Many RequestsWhy one JS thread can serve thousands of connections, what happens the moment you block it, and where CPU work belongs instead.
- Graceful Shutdown and Connection DrainingYour orchestrator kills your process on every deploy. What SIGTERM actually starts, why the order of draining matters, and where the dropped requests go.
Designing An API
- REST Resource Design That Ages WellResources are nouns and the verb already rides in the request. Map the methods honestly, stop nesting, and know when RPC is the better answer.
- Status Codes and an Error Contract Clients Can TrustThe status code is the only part of a response that machines read. Choose it honestly, ship one error body forever, and never let a stack trace out.
- Validating at the BoundaryTreat every request as hostile, parse it into a typed value at one gate, reject unknown keys, and turn schema failures into clean field-level 400s.
- Pagination, Filtering and SortingWhy LIMIT and OFFSET fall apart at a million rows, and how cursor pagination, deterministic sorting, indexed filters and page caps keep list endpoints fast.
- Versioning Without Breaking ClientsYou cannot redeploy other people's apps, so ship additive changes, write tolerant clients, and reach for a new version only when you truly must.
- GraphQL: When It Earns Its KeepThe problem GraphQL solves, how schemas and resolvers actually work, the N+1 and caching costs it adds, and the honest cases where REST wins.
- Webhooks: Receiving, Verifying and ReplayingA webhook is an unauthenticated write until you verify it: sign the raw body, reject stale timestamps, dedupe by event id, and answer fast.
- Idempotency Keys for Money-Safe EndpointsStop the tap-Pay-twice double charge: send an Idempotency-Key, store key-to-response inside the same transaction as the effect, and let a unique index settle the race.
Data and Databases
- SQL and Postgres for JavaScript DevelopersMake the jump from JS loops to set-based SQL: SELECT, JOIN, GROUP BY, three-valued NULL logic, the right Postgres types, and always-parameterised queries.
- Data Modelling and NormalisationStore each fact once: entities and relations, one-to-many and many-to-many, keys, the normal forms demystified, denormalisation, and jsonb.
- Indexes: How a Query Gets FastHow a B-tree turns a full-table scan into a handful of page reads, how to read EXPLAIN ANALYZE, and when an index helps, hurts, or does nothing at all.
- Transactions and Isolation LevelsWhy two writes must both land or neither: ACID, the anomalies that quietly corrupt data, Postgres isolation levels, locks, deadlocks and retries.
- Query Builders vs ORMsThree ways to talk to a database from JavaScript: raw driver, query builder, and ORM. What each gains, what leaks, and how to actually choose.
- Connection Pooling, and Why It BitesWhy a database connection is expensive, how a pool reuses it, why small pools win, how exhaustion takes you down at 3am, and the serverless fix.
- Migrations You Can Roll ForwardChange a live database without downtime: versioned migrations, the expand and contract pattern, safe locks, batched backfills, and forward-fixes.
- The N+1 ProblemOne query for the list and one more per row looks clean in review but turns a fast endpoint into a four-second one. How to spot and kill N+1.
Auth and Identity
- Passwords, Hashing and argon2Why plaintext and fast hashes lose, how salts and memory-hard argon2id win, plus constant-time checks and modern password policy.
- Sessions vs JWT: The Real TradeoffSessions are an opaque id plus a store you can delete from; JWTs trade that lookup for signed claims you cannot easily revoke. When to use which.
- Cookies Done Right: httpOnly, SameSite, ScopeEvery attribute on a Set-Cookie line turns off a specific attack. HttpOnly, Secure, SameSite, scope, prefixes, and the CSRF story, one switch at a time.
- OAuth and Social LoginOAuth delegates authorization, OIDC adds identity on top. The authorization code flow with PKCE, state, scopes, tokens and account linking, step by step.
- Magic Links and PasswordlessPasswordless login done right: high-entropy single-use tokens, hashed at rest and consumed atomically, plus where email codes and passkeys fit.
- Authorization: Roles, Policies and OwnershipAuthentication is who you are; authorization is what you may do. Put ownership in the query, enforce in one layer, fail closed, and test it.
Scale and Reliability
- Caching Layers: Request, Data and CDNWhere to cache from browser to database, how HTTP caching and ETags really work, and how to survive invalidation, staleness and cache stampedes.
- Redis and the Shape of a CacheRedis as an in-memory data-structure server: its types, atomic commands, TTL and eviction, locking, pub/sub, and the pitfalls that bite in production.
- Background Jobs and QueuesGet slow, flaky, third-party work off the request path: enqueue it, return 202, and let idempotent workers retry safely toward a dead-letter queue.
- Retries, Backoff and Dead LettersRetry only transient, idempotent failures with exponential backoff and jitter, respect Retry-After, and dead-letter what is left.
- Rate Limiting and Abuse ControlPick a key, pick an algorithm, count it in one shared place, and answer abuse with 429 and Retry-After before it costs you money.
- File Uploads and Object StorageWhy blobs do not belong in your database, when to stream an upload, why presigned direct-to-storage is the default, and the validation you cannot skip.
- Scheduled Work: Cron in a Distributed WorldWhy setInterval is not a scheduler: locks and leader election, missed runs, overlap, DST, and running cron as a queue you can actually watch.
- Multi-Tenancy and Data IsolationShared, schema, or database per tenant: keep one customer's rows from ever reaching another, enforced in the database instead of by discipline.
- Observability: Logs, Correlation IDs, Metrics and TracesStructured logs, a request id threaded through every service, RED and USE metrics, p99 over averages, and traces with OpenTelemetry to answer why it broke.
Part 8
JavaScript and AI
Model Foundations
- What a Language Model Actually DoesA language model does one thing: turn a sequence of tokens into a probability for the next token, then repeat. Chat, code and agents are all that loop.
- Tokens, and Why They Cost YouThe model never sees your words, only tokens. Tokens set your bill, your context limit and your rate limit, so it pays to know how text splits.
- The Context Window as a BudgetThe context window is one shared budget for your prompt, history, retrieved text and the reply. They all compete, and overflow either errors or quietly forgets.
- Calling a Model From JavaScriptUnder every SDK is one HTTP POST: messages in, an assistant message out. Your API key bills to you, so it lives on the server, never the browser.
- Streaming a Response Into the UIStreaming shows tokens as the model makes them, so the first words land fast. How SSE, web streams, flushing, and cancellation fit together.
- Temperature, Sampling and DeterminismThe model hands you a probability distribution. Sampling turns it into a token, and temperature is the knob between reliable extraction and creative sprawl.
- System, User and Assistant RolesChat models feel like they remember you. They do not. Every call is stateless, memory is your code resending the transcript, and roles are how you steer it.
- Images, Audio and Documents as InputModern models read images, audio and PDFs, not just text. How they go in the messages array, why pixels cost tokens, and where vision quietly fails.
- Reasoning Models and Thinking BudgetsA newer class of model thinks before it answers using hidden, billed reasoning tokens. When that pays off, what it costs, and how to route around it.
Structured Output and Tools
- Structured Output You Can TrustGet JSON you can store and branch on: JSON mode, schema-constrained decoding, then validate the result because a valid shape can still be wrong.
- Tool (Function) Calling ExplainedA chat model cannot run code. It emits a request to call your function, your code runs it, you feed the result back. Here is the whole loop, slowly.
- Designing a Tool CatalogTool names, descriptions, and schemas are the API the model programs against. How to shape a catalog it picks from correctly, and where it breaks.
- The Agent LoopAn agent is a while loop around tool calling. Once you see the loop you can build it, cap it, and stop it looping forever or blowing the bill.
- Multi-Step Workflows and DurabilityA long agent run can die mid-flight. Checkpoint each step, make side effects idempotent, and resume instead of replaying the whole thing from zero.
- Human in the Loop: Approvals and InterruptsOnce an agent can send, pay, or delete, the model deciding alone is not enough. Gate the risky actions, pause for a human, and log who approved what.
- Sandboxed Code ExecutionLetting a model write and run code is the most useful tool you can hand it and the most dangerous. Here is how to run it isolated, capped, and ephemeral.
- MCP: Connecting Models to Your SystemsOne open protocol so any AI app can use any tool or data source. What a server exposes, how a host connects, and why it is a trust boundary.
Retrieval
- Embeddings and Vector Space, IllustratedAn embedding turns text into a vector so similar meanings sit close together, which is how semantic search, RAG and recommendations actually work.
- Cosine Similarity and Nearest NeighboursCosine, dot product and Euclidean distance compared, then k-nearest-neighbours and the approximate indexes (HNSW, IVF) that make vector search fast.
- Chunking: The Part Everyone Gets WrongChunking splits documents so retrieval finds the right passage. Size, overlap, structure-aware boundaries and metadata decide whether RAG works.
- Vector Search With pgvectorStore an embedding per row in Postgres, query by distance, add an HNSW index, and safely combine metadata filters with nearest-neighbour ranking.
- Hybrid Search and RerankingWhy pure vector search whiffs on exact terms, and how hybrid retrieval with BM25, reciprocal rank fusion, and a cross-encoder reranker fixes it.
- The RAG Pipeline End to EndRAG is this chapter's pieces in two phases: ingest offline, then retrieve, augment and generate per query. Here is the whole flow and where it breaks.
- Grounding, Citations and HallucinationA confident wrong answer is what gets AI features pulled. Grounding, citations and refusal are how you pin a model to its sources and check it.
- Query Rewriting and ExpansionThe user's literal words are often a bad search query. Rewrite follow-ups, expand terms, try HyDE, multi-query and decomposition to fix retrieval.
Memory and Context
- Conversation State and SummarisationA chatbot only remembers because your code resends the transcript. When it grows too big, summarise the old turns and keep the recent ones verbatim.
- Long-Term Memory Across SessionsAn assistant remembers you across sessions by extracting durable facts, storing them per user, and retrieving the relevant ones into a later prompt.
- Context Engineering: Spending the WindowPrompt engineering became context engineering: curating what enters the window, ordering it well, compressing it, and fencing off untrusted text.
AI in Production
- Evals: Testing Something Non-DeterministicNormal tests assume one right answer. Models do not give you one, so you need evals: a dataset, graders, and a tracked score that fails the build before the user does.
- Cost, Tokens and Rate LimitsAI features cost real money on every request and the bill scales with use. Here is where it goes, which levers move it, and how to cap it before it hurts.
- Caching Model ResponsesExact-match, semantic, and provider prompt caching for model calls: what each keys on, how to tune the threshold, and when a cache hit is dangerous.
- Prompt Injection and Untrusted InputUntrusted text can hijack a model because it reads instructions and data as one stream. Why prompt injection stays unsolved, and how to limit the damage.
- PII, Redaction and SafetyThe moment your feature calls a model you become a data processor. Minimise what leaves, scrub your logs, guard the output, and be ready to delete.
- Tracing and Observability for AIAn AI request fans out into rewrite, retrieval, rerank, tools and a generation, so trace every step with its prompt, tokens, cost and quality.
- Model Routing and FallbacksSending every request to one big model overpays and stakes the feature on one provider. Route by task, cascade, and fall back to stay cheap and up.
On Device
- Running Models in the BrowserThe browser can run real models locally now. Zero per-call cost, no round trip, data that never leaves the device, if you respect the size limits.
- Local and Edge Inference Beyond the BrowserCloud APIs are the default, but sometimes you should run the model yourself. When self-hosting or edge inference pays off, and when it is a costly trap.
Part 9
Under the Hood
The Pipeline
- From Source Text to Running CodeJavaScript is both interpreted and compiled: the engine runs your code immediately, then quietly recompiles the hot parts into faster machine code.
- Parsing, the AST and Lazy CompilationHow the engine turns source text into tokens and a syntax tree, and why lazy parsing makes your bundle size a startup cost, not just a download.
- Ignition: Bytecode and the InterpreterV8 rewrites your functions into compact bytecode and runs it on a small register machine called Ignition, which is why startup is cheap and what the optimizer reads from.
- Sparkplug and Maglev: Tiering UpWhy V8 has four tiers, not two: Sparkplug compiles bytecode fast, Maglev optimizes in the sweet spot, and hot code climbs as it warms up.
- TurboFan: The Optimising TierFor the hottest code V8 calls in TurboFan, which bets on the types it saw and turns generic operations into tight, specialised machine code.
- Speculation and Type FeedbackHow V8 watches your running code and records the types and shapes each operation sees, and why that memory makes consistent code fast and varied code slow.
- Deoptimization: Falling Off the Fast PathOptimised code bets the future resembles the past. When a guard fails the engine unwinds to the interpreter: the bailout, deopt loops, and how to avoid them.
Objects in Memory
- Hidden Classes (Shapes), IllustratedV8 gives every object a hidden class, or shape, that maps each property to a fixed slot, so building objects the same way keeps property access fast.
- Inline Caches: Mono-, Poly-, MegamorphicAn inline cache remembers the shape and slot of a property right at each spot in your code, so repeat reads skip the lookup while shapes stay consistent.
- Elements Kinds: How Arrays Really Store DataV8 tags every array with an elements kind for what it holds and how densely; that tag only ever degrades, so dense single-typed arrays stay fast.
- Numbers: Smis, Doubles and BoxingWhy V8 stores small integers inline as Smis but boxes doubles on the heap, and what that representation cost means for the numbers your loops touch.
- Strings in the Engine: Ropes and InternalisationHow V8 really stores strings: one-byte and two-byte buffers, cons-string ropes, slices, and internalised copies, and why concatenation is cheap now.
Memory Internals
- The Heap: Young Space and Old SpaceWhy V8 splits the heap into a small young space and a large old space, how bump-pointer allocation and promotion work, and why short-lived objects are cheap.
- Scavenge, Mark-Compact and Incremental MarkingHow V8 reclaims memory without freezing your app: the copying Scavenger for young space, Mark-Compact for old space, and the tricks that keep pauses short.
- Object Layout and What Memory Really CostsWhat a JavaScript object really costs: its hidden-class header, in-object versus spilled properties, pointers, and why a million tiny objects hurt.
- Finding Leaks With Heap SnapshotsHunt JavaScript memory leaks with heap snapshots: what leaks in a garbage-collected language, retained size, the retainers chain, and the three-snapshot recipe.
Measuring
- Benchmarking Traps and Dead-Code EliminationAlmost every hand-rolled speed benchmark lies. Warm-up, dead-code elimination and noise explain why, and how to measure for real.
- Reading a Flame ChartA profiler shows where your program's time really goes. Read a flame chart: sampling, self versus total time, and finding the true hot spot.
- Optimising in PracticeEngine internals are a scalpel, not a hammer. Measure first, fix the biggest cost, and reach for shapes and deopts only when a profiler earns it.
Part 10
Patterns and Architecture
Pattern Foundations
- What a Pattern Actually Is (and Isn't)A design pattern is a named, reusable solution to a recurring problem, and its real value is vocabulary. When patterns help in JavaScript, and when they hurt.
- Module and Revealing ModuleHow closures faked privacy before JavaScript had modules, the revealing variant, and why ES modules and hash-private fields mostly retired the IIFE.
- Factory Functions and the Factory PatternA factory is any function that returns an object. Why it often beats a class constructor in JavaScript, plus polymorphic, cached, and builder variants.
- Singleton, and Why It Usually HurtsOne shared instance sounds tidy, but it is global mutable state in disguise. When a module singleton is fine, when it leaks, and why passing it in wins.
- Prototype and CloningMake new objects by cloning a known-good template, and the shallow-versus-deep copy bug that quietly corrupts the original.
- Composition Over InheritanceWhy deep inheritance trees crack under change, and how to build behaviour from small has-a pieces instead: mixins, function wrappers, and duck typing.
Behavioural Patterns
- Observer and Pub/SubOne object changes and a list of observers react, without it knowing who they are. Build an emitter by hand, then dodge the listener leak that eats memory.
- StrategyA switch that everyone edits is the smell. Strategy pulls each branch behind one shape, and in JavaScript that shape is usually just a function.
- Command and UndoTurn an action into an object that knows how to do and undo itself, and undo, redo, queues and replay all fall out of one history stack.
- State MachinesBooleans that can disagree breed impossible states. Enumerate the states, allow only the legal transitions, and a whole class of UI bugs vanishes.
- MediatorWhen every component pokes every other one, route them through one central hub instead. The catch: that hub can swell into a god object.
- IteratorStop copy-pasting traversal into every caller. The iterator pattern hides how a collection is stored behind one contract that JavaScript already speaks.
- Template MethodWrite the fixed steps of an algorithm once and leave holes for the parts that vary. You meet it every time a framework calls your lifecycle hook.
- Chain of ResponsibilityA request walks a line of handlers until one takes it. The pattern behind middleware, event bubbling and escalation, plus the bug that stalls the chain.
Structural Patterns
- FacadeA facade is a simple front door over a messy subsystem: when one clean function is right, when it rots into a god object, and how not to trap the caller.
- AdapterAn adapter converts one interface into another so incompatible code fits: wrapping vendor SDKs, normalising providers, and how it differs from a facade.
- The Proxy Pattern (vs the Proxy Object)A stand-in with the same interface that controls access to a real object, its four classic kinds, and why the pattern is not the JS Proxy object.
- The Decorator Pattern (vs Decorator Syntax)Wrap a function or object to add behaviour at runtime, why it beats a subclass per combination, and how it differs from the @decorator syntax.
- CompositeTreat one object and a whole tree of them the same way. How the composite pattern runs the DOM and file systems, and when a plain array is better.
- FlyweightShare the parts of an object that repeat across thousands of instances so a million similar objects collapse onto a few, and know when it is even worth it.
Application Architecture
- Layered ArchitectureSplit a backend into a presentation, domain, and data layer, point every dependency downward, and your business rules become testable without a server or a database.
- Dependency Injection and Inversion of ControlInstead of reaching for the things it needs, code receives them. Why that one move makes it testable and swappable, and when a container earns its keep.
- Event-Driven DesignAnnounce what happened instead of calling the next service, so producers and consumers decouple, at the price of eventual consistency you plan for.
- Ports and Adapters (Hexagonal)Put your business rules in the middle, push every database, HTTP and email detail out to swappable adapters at the edge, and the core depends on nothing.
- CQRS: When It PaysUsing separate models to write and read data. Genuinely worth it for a few hard domains, and expensive over-engineering for almost everything else.
Resilience Patterns
- Circuit BreakerWhen a dependency dies, calling it harder kills you too. The breaker fails fast on purpose to stop one outage from becoming three.
- Timeouts and BulkheadsPut a deadline on every call and isolate resources per dependency, so one slow or hung service cannot drain the pool everyone shares.
- Graceful DegradationWhen something breaks, drop the non-essential and defend the core, so a dead recommendations service means a page without recommendations, not an error page.
- Composing Stability PatternsTimeout, retry, breaker, bulkhead and fallback are not alternatives. They are layers around one call, and the order is the program.