Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Technology handbook

JavaScript (ECMAScript 2026) — Language & Runtime

Modern JavaScript from language fundamentals through the seven additions in ECMAScript 2026.

Topics
61
Sections
9

Foundations

Modules and execution

Organize code with ES modules and understand bindings, scope and execution contexts.

  • Imports expose live bindings rather than copied variable values.
  • Modules have their own scope and execute in strict mode.
  • Avoid circular dependencies that read bindings before initialization.

Variables and closures

Use lexical scope and closures to preserve state without leaking mutable globals.

  • let and const follow lexical block scope.
  • Closures retain access to their surrounding bindings.
  • A const binding does not make its referenced object immutable.

Destructuring and spread

Extract values and compose arrays or objects with readable, non-mutating syntax.

  • Destructuring defaults apply to undefined rather than every falsy value.
  • Object and array spread make shallow copies.
  • Rest syntax collects remaining properties or arguments.

Language core

Objects and prototypes

Model values with objects, prototypes and classes without losing track of identity.

  • Property lookup can continue along the prototype chain.
  • Object equality compares identity rather than matching fields.
  • Use own-property checks when inherited properties are inappropriate.

Arrays and collection methods

Transform and search data with map, filter, reduce, find and the newer non-mutating methods.

  • Use map for transformation and filter for selection.
  • Supply a deliberate initial accumulator to reduce.
  • Prefer copying sort or reverse methods when callers share the array.

Errors and resource cleanup

Create useful errors and release resources predictably with modern cleanup patterns.

  • Throw Error objects with actionable messages and useful causes.
  • Use finally for cleanup that must run after success or failure.
  • Avoid returning from finally because it can override earlier outcomes.

Primitive values and coercion

Distinguish value types, equality rules and explicit conversion from surprising coercion.

  • Prefer explicit conversion where input types are uncertain.
  • Understand that strict equality still has NaN and signed-zero subtleties.
  • Use Object.is when its equality semantics match the task.

this and binding

Predict this from the call site and choose bind, call, apply or arrow functions deliberately.

  • Ordinary function this depends on how the function is called.
  • Arrow functions capture this from their surrounding scope.
  • bind creates a callable with a chosen receiver and optional leading arguments.

Classes and private fields

Define class behavior, inheritance and truly private state with modern syntax.

  • Private fields enforce class-scoped access at runtime.
  • Static members belong to the constructor rather than its instances.
  • Call super before using this in a derived constructor.

Regular expressions

Match structured text with readable patterns, named groups and safe escaping.

  • Use named capture groups to make extraction easier to interpret.
  • Escape dynamic literal text before constructing a pattern.
  • Avoid catastrophic backtracking on untrusted large inputs.

Typed arrays and DataView

Read and write binary data with explicit widths, endianness and shared buffers.

  • Typed arrays view an ArrayBuffer with a fixed element format.
  • DataView allows explicit byte order for mixed-width binary fields.
  • Respect view offsets and lengths when sharing a buffer.

Async JavaScript

Promises and async

Compose asynchronous work with promises, async functions, cancellation and the event loop.

  • An async function always returns a promise.
  • Await pauses that function without blocking the whole thread.
  • Handle rejections and cancellation at the owning operation boundary.

Web workers

Move CPU-heavy work off the main thread and communicate with structured messages.

  • Workers run in a separate execution context from the page.
  • Send structured-cloneable messages or transferable buffers.
  • Account for messaging overhead before moving small tasks off-thread.

Iterables and generators

Build lazy synchronous or asynchronous data pipelines with iterable protocols and yield.

  • An iterable supplies an iterator through the appropriate symbol method.
  • Generators suspend at yield and resume on the next request.
  • Close iterators when exiting a resource-owning sequence early.

Promise combinators

Choose all, allSettled, race or any according to failure and completion semantics.

  • all requires every input to fulfill and rejects on a failure.
  • allSettled reports each outcome without failing for an input rejection.
  • race takes the first settlement while any takes the first fulfillment.

AbortController

Cancel fetches and cooperative asynchronous work with a shared abort signal.

  • Pass the controller's signal to APIs that support cancellation.
  • Calling abort does not automatically stop unrelated promises.
  • Check cancellation before committing a late asynchronous result.

ES2026 additions

Map and WeakMap upsert

Use getOrInsert and getOrInsertComputed to replace has/get/set boilerplate.

  • getOrInsert keeps an existing value or inserts a default.
  • getOrInsertComputed calls its initializer only when the key is absent.
  • Check runtime support and retain valid WeakMap key types.

Iterator.concat

Join iterators lazily without materializing intermediate arrays.

  • Consume input iterables sequentially through one lazy iterator.
  • Values are produced on demand instead of copied into a combined array.
  • An unbounded first input prevents later inputs from being reached.

Uint8Array base64 and hex

Encode and decode binary data directly with the new typed-array methods.

  • Use fromBase64 or fromHex to decode supported text formats.
  • Use toBase64 or toHex to encode a byte array.
  • Validate input format and handle decoding errors at the boundary.

Math.sumPrecise

Sum floating-point values with a numerically stable algorithm.

  • Accumulate numeric values with less intermediate rounding error.
  • Do not treat precise summation as exact decimal arithmetic.
  • Define handling for non-finite inputs in the application.

Array.fromAsync

Collect async iterables and promise values into an array in input order.

  • Consume asynchronous iterables through a promise-returning array constructor.
  • Await yielded values and any asynchronous mapping operation.
  • Remember the completed array still retains all collected values in memory.

JSON.parse source text

Inspect source text for selected JSON values while parsing large or precise data.

  • Use the reviver context's source for supported primitive values.
  • Recover precise numeric text before converting it into a domain type.
  • Do not assume an already-rounded Number preserves the original digits.

Error.isError

Recognize error values across realms without relying on instanceof alone.

  • Use the built-in error brand check where supported.
  • Recognize genuine Error instances created in another realm.
  • Keep validation for non-Error thrown values at catch boundaries.

Set methods

Use union, intersection, difference and symmetricDifference for clear set operations.

  • Use union and intersection to combine or retain memberships.
  • Use difference and symmetricDifference for exclusion and mismatches.
  • These operations produce new sets without editing the original membership.

RegExp.escape

Escape arbitrary text before embedding it in a regular expression safely.

  • Use RegExp.escape for literal text inserted into a regex.
  • Keep intended regex operators outside the escaped fragment.
  • Verify runtime support rather than writing an incomplete escaping pattern.

Promise.try

Normalize synchronous throws and returned promises into one rejection-aware flow.

  • Invoke a callback and convert synchronous throws into rejections.
  • Adopt a returned promise so callers get one async error path.
  • Await or catch the resulting promise instead of ignoring failures.

Shipping JavaScript

Feature detection

Check runtime support before shipping new language and built-in APIs.

  • Check for the actual property or capability before calling it.
  • Distinguish available type declarations from runtime implementation.
  • Provide a compatible fallback or require a supported runtime.

TC39 proposal stages

Read proposal stages correctly and distinguish shipped features from experiments.

  • A proposal's stage describes specification progress, not universal availability.
  • Verify current proposal status before relying on experimental syntax.
  • Check target engines separately from standard inclusion.

Modules in browsers and Node

Choose ESM boundaries, package exports and runtime-compatible import paths.

  • Use package exports to describe supported entry points.
  • Match browser import URLs and Node package-resolution rules.
  • Test ESM and CommonJS boundaries instead of assuming interoperation.

Array methods

Array.prototype.map

Build a new array by transforming every element with a callback.

  • Returns a new array of the same length and never mutates the source.
  • The callback receives (element, index, array), so an index is available without a counter.
  • Returning nothing yields undefined entries — use filter or flatMap when some elements should be dropped.

Example: map-basics.js

const rows = [
  { id: 1, name: "Ada", hours: 7 },
  { id: 2, name: "Linus", hours: 3 },
];

// One output element per input element.
const options = rows.map(row => ({ value: row.id, label: row.name }));

// The index is the second argument — no counter needed.
const numbered = rows.map((row, index) => (index + 1) + ". " + row.name);

console.log(options.length === rows.length); // true: map never drops elements
console.log(numbered); // ["1. Ada", "2. Linus"]

Rendering a list from data: Turn an array of API records into view models or elements, one per row, without touching the fetched data.

Array.prototype.filter

Build a new array of the elements a predicate keeps.

  • Keeps every element whose callback returns a truthy value, in their original order.
  • Always returns an array — an empty one when nothing matches, never undefined.
  • Filtering before mapping avoids transforming elements that are about to be discarded.

Applying a search or status filter: Narrow a loaded collection to the rows matching a query or a status before paging it, leaving the original list intact.

Array.prototype.reduce

Fold an array into a single value by accumulating one element at a time.

  • Takes (accumulator, element, index, array) and an optional initial value.
  • Omitting the initial value uses the first element and throws on an empty array — pass one.
  • Any array method can be written as a reduce, but a map or filter states the intent more plainly.

Example: reduce-total.js

const invoice = [
  { item: "Keyboard", price: 4500, qty: 1 },
  { item: "Cable", price: 300, qty: 3 },
];

// Pass the initial value: an empty array throws without it.
const total = invoice.reduce((sum, line) => sum + line.price * line.qty, 0);

console.log(total); // 5400
console.log([].reduce((a, b) => a + b, 0)); // 0, not a TypeError

Totals and groupings: Sum an invoice, count occurrences, or group records by a key into an object in a single pass.

Array.prototype.find and findLast

Return the first or last element matching a predicate, or undefined.

  • find scans from the start and findLast from the end; both stop at the first match.
  • They return the element itself, unlike findIndex and findLastIndex which return its position.
  • undefined is also a legal element value, so use findIndex when absence must be distinguished.

Looking up one record by id: Pull a single item out of a loaded collection — the selected row, the default address — without a second request.

Array.prototype.flat and flatMap

Flatten nested arrays by one level, or map and flatten in one pass.

  • flat() flattens one level; flat(Infinity) flattens completely.
  • flatMap(fn) is map followed by flat(1), and is how a callback returns zero or many items per element.
  • Both skip empty slots in sparse arrays.

Expanding one row into many: Turn each order into its line items, or drop an element by returning an empty array from the callback.

Array.prototype.sort and toSorted

Order an array in place, or get an ordered copy.

  • sort mutates and returns the same array; toSorted returns a new one and leaves the source alone.
  • Without a comparator, elements are compared as strings, so 10 sorts before 9.
  • The comparator must return a negative number, zero or a positive number, consistently for every pair.

Sorting a table column: Order rows by date, price or name when a header is clicked, using toSorted so the fetched data keeps its original order.

Array.prototype.slice and splice

Copy a section of an array, or insert and remove elements in place.

  • slice(start, end) returns a copy and leaves the source untouched; end is exclusive.
  • splice(start, count, ...items) mutates the array and returns the removed elements.
  • Negative indexes count from the end, and toSpliced gives splice's result without mutating.

Paging and editing a list: Take one page out of a result set with slice, and remove or insert a row in a draft list with toSpliced.

Array.prototype.includes and indexOf

Test membership, or find the position of a value.

  • includes returns a boolean and matches NaN; indexOf returns -1 for absence and never matches NaN.
  • Both compare with strict equality, so two equal-looking objects do not match.
  • indexOf accepts a starting position, which is how repeated values are found.

Checking a selection: Test whether an id is already selected before adding it, or find where it sits so it can be removed.

Array.prototype.some and every

Test whether any, or all, elements satisfy a predicate.

  • Both short-circuit: some stops at the first true, every at the first false.
  • every returns true for an empty array and some returns false — the vacuous cases interviews ask about.
  • Both return a boolean, so pair them with find when the matching element itself is needed.

Form and permission checks: Enable submit because every field is valid, or warn because some item in a cart is out of stock.

Array.prototype.at

Read an element by index, counting from the end with a negative one.

  • at(-1) is the last element, which bracket notation cannot express directly.
  • Returns undefined for an out-of-range index rather than throwing.
  • Works on strings and typed arrays as well as arrays.

Reading the latest entry: Take the most recent message in a conversation or the final segment of a path without writing list[list.length - 1].

Array.from and Array.of

Build an array from an iterable or array-like value, or from its arguments.

  • Array.from takes an optional map function, so from(x, fn) avoids a second pass.
  • Array.from({ length: n }, (_, i) => i) is the idiomatic range.
  • Array.of(7) is [7] while Array(7) is seven empty slots — the reason Array.of exists.

Converting DOM and Set results: Turn a NodeList, a Set or a Map's entries into a real array so every array method becomes available.

Array.prototype.join

Join elements into a string with a separator.

  • null and undefined join as empty strings, not as the text "null".
  • The default separator is a comma, which is what toString and string coercion use.
  • Joining is clearer and usually faster than repeated concatenation in a loop.

Rendering a list inline: Print tags, authors or active filters as a comma-separated line, or build a path from segments.

String methods

String.prototype.split

Cut a string into an array on a separator or pattern.

  • Accepts a string or a regular expression, plus a limit for how many pieces to keep.
  • Splitting on "" splits by UTF-16 code unit and breaks emoji — use Intl.Segmenter for characters.
  • A capturing group in the pattern keeps the separators in the result.

Parsing structured text: Split a CSV line, a path or a comma-separated tag input into parts before validating each one.

String.prototype.replace and replaceAll

Replace the first match, or every match, with text or a function's result.

  • replace with a string pattern replaces only the first occurrence; replaceAll replaces all of them.
  • $& and $1 in the replacement refer to the match and its capture groups; $$ is a literal dollar sign.
  • A replacer function receives the match and its groups, so each replacement can be computed.

Templating and escaping: Substitute placeholders in a message, or escape characters before putting user text into a URL or a pattern.

String.prototype.slice and substring

Take part of a string by position.

  • slice accepts negative indexes; substring clamps them to zero and swaps reversed arguments.
  • Neither mutates — strings are immutable, so both return a new string.
  • at(-1) reads the last character, which slice(-1) also returns as a one-character string.

Truncating and excerpting: Cut a summary to a card's length, take a filename's extension, or read a fixed-width field from a record.

String.prototype.trim, padStart and padEnd

Remove surrounding whitespace, or pad a string to a fixed width.

  • trimStart and trimEnd trim one side only; all three return a new string.
  • padStart is how numbers are zero-padded: String(n).padStart(2, "0").
  • Padding stops once the target length is reached, so a longer string comes back unchanged.

Cleaning input and aligning output: Trim a pasted email before validating it, and pad minutes and seconds so durations line up in a column.

String.prototype.startsWith, endsWith and includes

Test where, or whether, a substring appears.

  • All three take an optional position and return a boolean rather than an index.
  • They are case-sensitive, so normalize both sides before comparing user input.
  • includes cannot take a regular expression — use test or match for a pattern.

Routing and type-ahead filtering: Decide whether a path belongs to a section, or filter a list as someone types into a search box.

String.prototype.matchAll

Read every match of a pattern, with its capture groups and positions.

  • Requires the global flag and returns an iterator of full match objects.
  • Named groups are read from match.groups, which is clearer than numbered indexes.
  • match with /g returns matched text only and drops the groups and indexes.

Extracting every occurrence: Pull all mentions, links or template placeholders out of a block of text along with where each one starts.

String.prototype.localeCompare

Compare strings the way a reader's language orders them.

  • Returns a negative number, zero or a positive number, so it drops straight into sort.
  • Options set sensitivity and numeric ordering, so "item10" can sort after "item9".
  • Intl.Collator reuses one comparator and is faster when sorting a long list.

Sorting names for people: Order a directory or product list so accented and case-different names fall where a reader of that language expects.

String.prototype.normalize

Put equivalent Unicode sequences into one canonical form before comparing.

  • An accented letter can be one code point or a base letter plus a combining mark; the two are not === until normalized.
  • NFC is the usual choice for storage and comparison; NFD separates the base and the marks.
  • Normalizing then stripping combining marks is how accent-insensitive search is built.

Matching user-entered text: Compare a pasted name against a stored one so two identical-looking strings do not fail to match.

Object & JSON

Object.keys, values and entries

Read an object's own enumerable keys, values or key-value pairs as an array.

  • Only own enumerable string-keyed properties are returned; inherited and symbol keys are skipped.
  • Integer-like keys come first in ascending order, then string keys in insertion order.
  • Object.entries pairs with Object.fromEntries to map or filter an object through array methods.

Iterating a record: Render a settings object as rows, or count how many fields of a form object have been filled in.

Object.assign and object spread

Copy own enumerable properties from one or more sources onto a target.

  • Both copy one level deep, so nested objects stay shared with the source.
  • Object.assign mutates its target and returns it; spread always builds a new object.
  • Spread copies values while assign triggers setters on the target — the reason the two can differ.

Merging defaults with overrides: Build a config from defaults plus user options, or produce the next state object without mutating the previous one.

Object.freeze and Object.seal

Make an object's properties unwritable, or its shape fixed.

  • freeze is shallow — nested objects stay mutable unless frozen too.
  • Writes fail silently in sloppy mode and throw a TypeError in strict mode and in modules.
  • seal is the weaker form: existing properties stay writable, but none can be added or removed.

Protecting shared constants: Keep a shared configuration or lookup table from being edited by accident somewhere else in the app.

Object.fromEntries

Build an object from key-value pairs.

  • Accepts any iterable of pairs, including a Map and URLSearchParams.
  • Later duplicate keys overwrite earlier ones.
  • Object.entries → array method → Object.fromEntries is the standard way to map or filter an object.

Reading query parameters: Turn a URL's search parameters or a form's entries into a plain object to validate and pass around.

Object.create and prototypes

Create an object with an explicit prototype, or with none at all.

  • Object.create(null) has no prototype, so there is no inherited toString or __proto__ to collide with.
  • A second argument takes property descriptors, which an object literal cannot express.
  • getPrototypeOf reads the link; setPrototypeOf changes it and is slow enough to avoid in hot paths.

Safe dictionaries: Hold user-supplied keys — headers, counts by word — without a key such as "constructor" hitting an inherited property.

Object.defineProperty and descriptors

Define a property together with its writability, enumerability and accessors.

  • Properties defined this way default to non-writable, non-enumerable and non-configurable.
  • A descriptor holds either value and writable, or get and set — never both pairs.
  • getOwnPropertyDescriptor reads one back, which is how an accessor is copied faithfully.

Computed and hidden fields: Expose a derived value as a getter, or keep an internal field out of JSON.stringify and for-in loops.

JSON.stringify

Serialize a value to JSON, with optional filtering and indentation.

  • undefined, functions and symbols are dropped from objects and become null inside arrays.
  • A toJSON method decides a value's own serialized form — how Date becomes a string.
  • The replacer chooses which keys to keep; the third argument sets indentation for readable output.

Sending and storing state: Put a request body on the wire or a draft into localStorage, leaving out fields the server must not receive.

JSON.parse and the reviver

Turn JSON text back into values, transforming entries as they are read.

  • Throws a SyntaxError on malformed input, so parsing untrusted text belongs in a try/catch.
  • The reviver runs for every key from the innermost outward, and returning undefined drops a key.
  • Dates arrive as strings — a reviver or a schema parser is what turns them back into Date objects.

Example: safe-parse.js

export function readDraft(key) {
  const stored = localStorage.getItem(key);
  if (!stored) return null;
  try {
    return JSON.parse(stored, (field, value) =>
      field === "savedAt" ? new Date(value) : value);
  } catch {
    localStorage.removeItem(key);
    return null;
  }
}

Reading stored or fetched data: Restore a saved draft from localStorage, rejecting corrupted data instead of letting it break the page.

structuredClone

Deep-clone a value, including Map, Set, Date and typed arrays.

  • Handles cycles, which a JSON round-trip cannot.
  • Functions, DOM nodes and class identity are not cloned — a function throws a DataCloneError.
  • Available in browsers and Node without a library, and is the algorithm postMessage already uses.

Snapshotting state: Take a true copy of a nested draft before an edit so cancelling restores it exactly.

Promise API

Promise.all and Promise.allSettled

Run promises concurrently and wait for all of them.

  • all rejects as soon as any input rejects, and the other work keeps running unless it is aborted.
  • allSettled never rejects: each result is {status, value} or {status, reason}.
  • Both preserve input order in the results, whichever finished first.

Example: load-page-data.js

async function loadDashboard(userId, signal) {
  const [user, permissions, alerts] = await Promise.all([
    fetch("/api/users/" + userId, { signal }).then(r => r.json()),
    fetch("/api/users/" + userId + "/permissions", { signal }).then(r => r.json()),
    fetch("/api/alerts", { signal }).then(r => r.json()),
  ]);
  return { user, permissions, alerts };
}

// Promise.all rejects as soon as any input rejects; the rest keep running
// unless the shared AbortController is aborted.

Loading a page's data at once: Fetch the user, their permissions and their notifications together, still rendering partial content with allSettled when one call fails.

Promise.race and Promise.any

Settle on the first promise to finish, or on the first to succeed.

  • race settles with the first result, rejection included; any ignores rejections until one fulfils.
  • any rejects with an AggregateError only when every input rejects.
  • race against a timer is the timeout idiom — pair it with AbortController so the loser is actually cancelled.

Timeouts and mirrors: Give a request a deadline, or take whichever of several mirrors or caches answers first.

Promise.resolve, reject and chaining

Make a settled promise, and know what then returns.

  • then always returns a new promise, so a value returned inside it becomes the next resolution.
  • Returning a promise inside then adopts it rather than nesting it.
  • catch(fn) is then(undefined, fn), and finally passes the result through untouched.

Normalizing sync and async: Wrap a cached value or a callback API so every caller gets a promise and one error path.

Ask follow-up questions on any topic in your dashboard.

Start learning