β All lessons
JavaScript
All JavaScript snippets Β· 200
Every snippet has its own focus page with an explanation and the output it produces.
Variables Β· 5
- let vs constlet allows reassignment; const binds the variable permanently to its initial value.
- const configconst for values that never change, let for counters or state that updates over time.
- const mutationconst prevents reassignment of the variable itself, but the object it points to is still mutable.
- var hoistingvar declarations are hoisted to the top of their function scope and initialized as undefined.
- var scope leakvar ignores block scope like if/for, while let and const are confined to their block.
Types Β· 5
- typeof operatortypeof is the primary way to check a value's type, but null and arrays are known gotchas.
- typeof nulltypeof null returns 'object' which is a JavaScript bug kept for backwards compatibility β always use === null instead.
- implicit coercionJavaScript converts types automatically in arithmetic β + with a string causes string concatenation, while -, *, / convert to numbers.
- loose equality== performs type coercion before comparing β use === to avoid surprising results.
- explicit conversionAlways convert types explicitly when combining user input (strings) with numbers to avoid concatenation instead of addition.
Operators Β· 7
- strict equalityStrict equality === never coerces types; always prefer it over == to write predictable comparisons.
- logical operators&& returns the first falsy or last value; || returns the first truthy or last value β used heavily for defaults.
- nullish coalescing?? differs from || by only treating null and undefined as missing β 0, '', and false are valid values.
- nullish defaults?? lets 0 and false be valid config values while still providing fallbacks for truly missing options.
- optional chaining?. short-circuits to undefined instead of throwing when a property doesn't exist on null or undefined.
- nested accessCombining ?. with ?? gives a clean way to safely read nested data and fall back to a default without if-chains.
- logical assignmentLogical assignment operators combine a logical check with assignment, useful for initializing or updating values conditionally.
Conditionals Β· 4
- if/else chainif/else if chains evaluate conditions top to bottom and execute the first matching block.
- ternary operatorThe ternary operator is best for simple inline decisions that return a value.
- switch statementswitch cases fall through to the next unless broken β useful when multiple values share the same outcome.
- switch fallthroughWithout break, execution falls through into the next case β often a bug but sometimes intentional.
Loops Β· 6
- for loopThe for loop gives full control over initialization, condition, and increment.
- for...of loopfor...of works on any iterable (arrays, strings, maps, sets) and gives the value directly without needing an index.
- for...in loopfor...in iterates the enumerable property keys of an object, not values directly.
- for...in arraysfor...in on an array gives string index keys not values β use for...of for arrays to avoid this trap.
- while loopsdo-while always runs the body at least once; while may never run if the condition starts false.
- break/continuebreak stops the entire loop; continue jumps to the next iteration skipping remaining statements in the current one.
Functions Β· 18
- function hoistingFunction declarations are hoisted completely β you can call them before they appear in the source.
- function expressionsFunction expressions are assigned at runtime β they cannot be called before their definition like declarations can.
- arrow functionsArrow functions with a single expression implicitly return it β wrap objects in () to distinguish from a block body.
- arrow thisArrow functions inherit 'this' from their enclosing lexical scope β never use them as object methods that need 'this'.
- default paramsDefault parameters activate only when the argument is undefined β not when it is null or 0.
- rest paramsRest parameters always produce a real array β unlike the old arguments object which is array-like but not an array.
- IIFE patternIIFE (Immediately Invoked Function Expression) creates an isolated scope β the classic pre-module encapsulation pattern.
- higher-order functionsHigher order functions accept or return functions β the foundation of composition, callbacks, and most array methods.
- recursionEvery recursive function needs a base case that stops the recursion β without it you get a stack overflow.
- curryingA curried function collects arguments one at a time and only runs when it has received enough.
- curried pipelineCurried functions become building blocks β each one partially applied creates a new reusable step in a pipeline.
- pipe/composepipe and compose do the same thing in opposite orders β pipe reads like a sequence of steps, compose like nested calls.
- data pipelinepipe makes the data flow readable β each step does one job and passes its result cleanly to the next.
- once functiononce is useful for initialization logic that should only run once β subsequent calls return the cached result silently.
- debouncedebounce collapses rapid calls into one β the function only fires after the user pauses, ideal for search inputs.
- throttlethrottle ensures a function fires at most once per interval β useful for scroll, resize, or mousemove handlers.
- debounce vs throttledebounce waits for silence before firing; throttle fires immediately but caps frequency β they solve different problems.
- generator sendPassing a value to next(value) injects it as the result of the yield expression β enabling two-way communication with a generator.
Scope Β· 2
Closures Β· 7
- closure basicsinner retains access to count even after outer has returned β this is a closure.
- closure counterThe returned object methods all share the same closed-over count β exposing controlled mutations on private state.
- var loop bindingvar is function-scoped so all callbacks close over the same variable; let creates a new binding per loop iteration.
- closure factoryEach function returned by makeMultiplier closes over its own factor β closures enable parameterized function generation.
- memoizationThe cache object lives in the closure β subsequent calls with the same args skip the computation entirely.
- partial applicationPartial application fixes some arguments upfront and returns a function waiting for the rest β a practical use of closures.
- private closureFactory functions with closures provide true privacy β unlike class properties, the private variables are physically inaccessible.
Objects Β· 13
- object literalsObject literals use dot or bracket notation for access β bracket notation is needed for dynamic or special-character keys.
- computed keysComputed keys with [] allow dynamic property names determined at runtime β useful for building objects from variables.
- getters/settersGetters and setters let you add logic to property reads and writes without changing how the API looks to callers.
- object iterationkeys/values/entries return arrays letting you use array methods like map and filter on object data.
- object transformObject.fromEntries combined with entries lets you map or filter objects the same way you would an array.
- Object.freezeFrozen objects silently ignore writes in non-strict mode β use for constants like config objects you never want mutated.
- object spreadSpread copies top-level properties β later keys override earlier ones, but nested objects are still shared by reference.
- shallow copySpread only clones the top level β nested objects remain the same reference, so mutations affect both copies.
- this keywordthis is determined at call time β when you detach a method and call it as a plain function, this is no longer the object.
- this bindingRegular functions in callbacks get their own this (usually undefined in strict mode); arrow functions inherit this from the class.
- ES6 shorthandWhen a variable name matches the key name, you can omit the colon and value β keeps object literals concise.
- Object.createObject.create lets you set a specific prototype without using classes β the base of prototypal inheritance patterns.
- definePropertyProperty descriptors give you fine-grained control over how properties behave β the foundation of how freeze and getters work internally.
Arrays Β· 17
- array basicsat() accepts negative indices as a clean alternative to arr[arr.length - n] for accessing from the end.
- push/pop/shiftpush/pop work on the end; unshift/shift work on the front β all four mutate the original array.
- array mapmap always returns a new array of the same length β the original is never modified.
- array filterfilter returns a new array containing only the elements for which the callback returns true.
- array reducereduce takes an accumulator and each element β the initial value is the starting accumulator.
- reduce to objectreduce is not just for numbers β it can build objects, maps, or any accumulated structure from an array.
- find/findIndexfind returns the element itself or undefined; findIndex returns the index or -1 if not found.
- some/everyevery short-circuits on the first false; some short-circuits on the first true β both return a boolean.
- array flatflat(1) flattens one level deep; flatMap is map then flat(1) β useful for one-to-many transformations.
- slice/spliceslice returns a new array and never mutates; splice modifies the array in place and returns removed elements.
- array sortWithout a comparator, sort() converts to strings β '10' < '2' alphabetically, so always pass (a, b) => a - b for numbers.
- Array.fromArray.from is the clean way to turn strings, Sets, Maps, and NodeLists into real arrays β the optional map function adds power.
- Array.from dataArray.from with a map function is the cleanest way to generate arrays of computed values without a loop.
- method chainingChaining filter β sort β map reads like a description of what you want β each step passes a new array to the next.
- sort mutationsort, reverse, and splice mutate the original array β always spread or slice first when you want a non-destructive sort.
- reduceRightreduceRight works right to left β directly mirrors how compose applies functions from innermost to outermost.
- destructure loopDestructuring in for...of loops unpacks each element on the fly β much cleaner than accessing [0] and [1] manually.
Destructuring Β· 6
- array destructureSkip positions with empty commas; collect the rest with ...rest β positional unpacking unlike object destructuring.
- object destructureRename with key: newName and provide fallbacks with key = default β all within the same destructuring pattern.
- nested destructureDeep destructuring can be expressive but quickly becomes hard to read β know when to just use dot notation.
- param destructureDestructuring params with defaults makes function signatures self-documenting and removes the need for options.x inside the body.
- swap variablesArray destructuring on the left side of an assignment is the cleanest way to swap two variables in place.
- iterable destructureAny iterable β strings, Sets, Maps, generators β can be destructured using array destructuring syntax.
Spread Β· 3
- spread operatorSpreading arrays creates a shallow copy β mutations to the copy don't affect the original for flat arrays.
- spread argsSpreading into a function call replaces the old Function.apply(null, args) pattern with cleaner syntax.
- string spreadSpreading a string creates an array of its characters β combine with Set to get unique characters instantly.
Strings Β· 4
- string methodsStrings have dozens of built-in methods β includes, startsWith, endsWith are cleaner than indexOf for existence checks.
- trim/split/replacereplace only replaces the first match β use replaceAll or a global regex to replace every occurrence.
- template literalsTemplate literals support any JavaScript expression inside ${} and preserve whitespace and newlines.
- tagged templatesTagged templates give you full control over how a template string is assembled β used in libraries like styled-components and SQL builders.
Numbers Β· 2
Math Β· 2
Classes Β· 8
- class syntaxClasses wrap constructor functions and prototype assignments in a cleaner syntax β under the hood it's still prototypes.
- class extendssuper() must be called in a child constructor before accessing this β it runs the parent's constructor.
- static membersStatic methods and fields are called on the class itself β they don't exist on instances and don't need new.
- private fieldsPrivate class fields with # are enforced by the engine β they cannot be accessed or patched from outside the class.
- fluent chainingReturning this from every mutating method enables fluent chaining β makes the API read like a sentence.
- abstract methodsJavaScript has no abstract keyword β throwing in the base method forces subclasses to override it or crash loudly.
- mixinsMixins compose behavior by wrapping base classes β avoids deep inheritance chains while sharing logic across classes.
- class iterableClasses that implement Symbol.iterator work with for...of, spread, and destructuring β making them feel like native collections.
Prototypes Β· 2
Error Handling Β· 6
- try/catchfinally always executes whether or not an error was thrown β ideal for cleanup like closing connections.
- custom errorsCustom error classes let you distinguish error types with instanceof and attach extra context like field names or codes.
- error typesDifferent error types help you identify what went wrong β TypeError for type issues, ReferenceError for missing variables, etc.
- unhandled rejectionAn unhandled promise rejection is a bug β always add .catch() or wrap await in try/catch to handle async failures.
- error causeError cause (ES2022) lets you wrap errors in higher-level errors while preserving the original β making stack traces much more useful.
- Result typeThe Result pattern makes errors visible in return types β callers are forced to handle both cases instead of forgetting try/catch.
Promises Β· 5
- promise basicsPromises have three states: pending, fulfilled, rejected β once settled they never change state.
- promise chainingEach .then receives the previous return value β if a then throws, execution jumps to the nearest .catch.
- Promise.allPromise.all rejects immediately if any promise rejects β use Promise.allSettled if you want all results regardless.
- Promise.allSettledallSettled never rejects β every result comes back with a status of fulfilled or rejected plus the value or reason.
- race/anyrace takes the first to settle (even rejected); any takes the first to fulfill and only rejects if all fail.
Async/Await Β· 9
- async/awaitAn async function always returns a Promise β await unwraps it, making async code look and read like synchronous code.
- await errorstry/catch with await works just like synchronous error handling β any rejected promise inside try is caught.
- parallel awaitAwaiting in a loop runs each promise one after another β use Promise.all to run independent async tasks concurrently.
- async generatorsAsync generators combine generators and async/await β use for...await...of to consume them one value at a time.
- lazy paginationAsync generators are perfect for paginated APIs β each page is fetched only when the next iteration is requested.
- retry backoffRetry with exponential backoff is a standard pattern for unstable network calls β doubling the delay reduces server pressure.
- promise timeoutPromise.race with a timeout promise is the standard way to cancel a hanging async operation.
- async methodsAsync methods on classes work exactly like async functions β await can be used inside and they return Promises.
- for await...offor await...of works on any object with [Symbol.asyncIterator] β the standard way to consume streams and async generators.
Generators Β· 4
- generatorsGenerators execute lazily β each next() call resumes from the last yield until the next one or the function returns.
- generator iterableBecause generators implement the iterator protocol, they work anywhere an iterable is expected β spread, for...of, destructuring.
- infinite generatorInfinite generators are safe because they are lazy β take() breaks out of the loop after pulling only what it needs.
- lazy pipelineGenerator pipelines are entirely lazy β no intermediate arrays are created, and values are computed only as consumed.
Iterators Β· 2
Map Β· 3
- Map basicsUnlike plain objects, Maps accept any value as a key (including objects and numbers) and maintain insertion order.
- Map vs ObjectObject keys collide with prototype properties like toString β Map has no such issue and allows any value as a key.
- frequency MapMap preserves insertion order and handles any key type β ideal for frequency counting and histogram building.
Set Β· 2
Proxy Β· 4
- proxy getThe get trap fires on every property read β use it to add default values, logging, or validation without changing the source object.
- proxy setThe set trap runs on every property write β perfect for building type-safe or validated data objects without a class.
- proxy loggingA logging Proxy is transparent to the rest of the code β no changes needed to the consumer, yet every access is recorded.
- proxy schemaA validation Proxy enforces rules on writes without exposing validation logic in the rest of the code.
Symbols Β· 4
- Symbol uniqueSymbols are guaranteed unique primitives β two Symbols with identical descriptions are still not equal to each other.
- Symbol keysSymbol-keyed properties don't show in for...in, Object.keys, or JSON.stringify β useful for attaching private metadata.
- well-known SymbolsWell-known Symbols like Symbol.iterator and Symbol.toStringTag let you hook into language-level behaviors on your own classes.
- Symbol.forSymbol.for() registers Symbols in a global registry β two calls with the same key return the same Symbol unlike Symbol().
Regex Β· 5
- regex basicstest() checks for a match; match() returns matches; replace() substitutes them β the g flag finds all, not just the first.
- capture groupsCapture groups () let you extract specific parts of a match β index 0 is the full match, 1+ are the groups.
- named groupsNamed capture groups (?<name>...) make your regex self-documenting and let you access parts by name not index.
- regex flagsi=case-insensitive, g=global (all matches), m=multiline (^ matches start of each line) β flags combine freely.
- stateful regexA regex with /g is stateful β it remembers lastIndex between calls. Create a new instance each time or reset lastIndex = 0.
Date Β· 3
- date basicsMonths are 0-indexed in JavaScript Date β January is 0, December is 11 β always add 1 when displaying.
- date differenceDates are numbers under the hood β subtracting two Date objects gives milliseconds, which you convert to any unit.
- date formatIntl.DateTimeFormat handles locale-aware date formatting β no manual string building needed.
JSON Β· 3
- JSON basicsJSON.stringify converts objects to strings for storage or transfer; JSON.parse reconstructs them β always returns a deep copy.
- JSON replacerThe replacer filters what gets serialized; the reviver transforms values back β use it to restore Dates, Maps, or sensitive-field stripping.
- JSON limitsJSON only handles strings, numbers, booleans, null, arrays, and plain objects β functions, undefined, and Symbols are silently dropped.
Design Patterns Β· 7
- observer patternObserver decouples producers from consumers β emitters don't know who's listening, listeners don't know who emits.
- factory patternFactory functions centralize object creation logic β callers just specify what they want, not how it's built.
- singletonThe Singleton pattern ensures shared global state like config or a DB connection is only initialized once.
- strategy patternStrategy replaces conditionals β instead of if-else on algorithm type, you swap in a different function at runtime.
- builder patternBuilder is ideal when object construction needs many optional steps β each step is explicit and the final build() creates the object.
- state machineA finite state machine makes all valid transitions explicit β any illegal event throws instead of causing silent corruption.
- command patternCommand pattern encapsulates each action as an object with execute and undo β making history and undo trivially composable.
Data Structures Β· 4
- stack LIFOStack's LIFO property is perfect for matching open/close pairs β the last opened must be the first closed.
- queue FIFOQueues process items in arrival order β used in BFS, task schedulers, and message brokers.
- linked listLinked lists use node references instead of contiguous memory β O(1) prepend but O(n) access by index.
- binary search treeBST inorder traversal yields values in sorted order β left subtree is always smaller, right is always larger.
Algorithms Β· 8
- binary searchBinary search is O(log n) β each comparison eliminates half the remaining candidates. Requires a sorted array.
- merge sortMerge sort is O(n log n) and stable β it divides the array in half recursively, then merges sorted halves back together.
- two pointersTwo pointers from both ends of a sorted array find pairs in O(n) instead of the brute-force O(nΒ²).
- sliding windowSliding window reuses the previous sum by adding the new element and removing the old one β O(n) instead of O(n*k).
- dynamic programmingBottom-up DP builds the answer from smaller subproblems β dp[i] is the minimum coins to make exactly i.
- flatten arrayRecursion handles unknown depth naturally β the base case (non-array) pushes the value, the recursive case digs deeper.
- BFS traversalBFS uses a queue to visit nodes level by level β the first path found to any node is the shortest (in unweighted graphs).
- DFS traversalDFS goes as deep as possible before backtracking β naturally implemented with recursion using the call stack.
Functional Patterns Β· 6
- immutable updateImmutable updates spread each level β never mutate state directly, always return a new object with the changed parts.
- compose reduceCombining filter and map into one reduce avoids creating an intermediate array β useful when working with large datasets.
- lensesLenses abstract getting and setting nested fields β they are composable and always produce new objects without mutation.
- tap functiontap injects logging or debugging into a pipeline without mutating the value or breaking the chain.
- Maybe monadMaybe prevents null reference errors by wrapping values β map skips the function if the value is null, enabling safe chaining.
- pipe orderpipe applies left to right (first function first); compose applies right to left (last function first) β different results for the same functions.
Performance Β· 3
- lazy propertiesLazy evaluation defers expensive computation until the value is needed β and caches it so the cost is paid only once.
- object poolObject pools avoid repeated allocation and GC β acquire a pre-made object, use it, then release it back for reuse.
- closure leaksClosures keep the entire outer scope alive β if you close over a large object you no longer need, null it out to allow GC.
Intl Β· 2
Web APIs Β· 3
- URL APIThe URL API parses and mutates URLs structurally β safer than string manipulation and handles encoding automatically.
- AbortControllerAbortController is the standard way to cancel pending fetch calls and other async operations in the browser.
- TextEncoderTextEncoder/Decoder convert between strings and Uint8Array bytes β essential for binary protocols, crypto, and WebSockets.