"What is new in JavaScript" is a warm-up that separates candidates who read release notes from those who learned the language once. ES2026 was ratified on 30 June 2026; knowing what it contains, what just missed it, and how to decide when a feature is safe to use is the senior version of the answer.
findLast/findLastIndex, change-by-copy arrays (toSorted, toReversed, toSpliced, with), hashbang grammar, symbols as WeakMap keys.Promise.withResolvers(), Object.groupBy/Map.groupBy, resizable and growable ArrayBuffer plus transfer(), RegExp v flag (set notation, string properties), Atomics.waitAsync, String.prototype.isWellFormed/toWellFormed.union, intersection, difference, …), sync iterator helpers, RegExp.escape, Promise.try, JSON modules and import attributes (with { type: 'json' }), RegExp pattern modifiers ((?i:…)), duplicate named capture groups in alternation, Float16Array and Math.f16round, redeclarable eval-introduced globals.Map.prototype.getOrInsert, getOrInsertComputed, also on WeakMap), Iterator.concat (iterator sequencing), Uint8Array base64 and hex (fromBase64, toBase64, fromHex, toHex), Math.sumPrecise (exact summation of doubles), Error.isError, Array.fromAsync, and JSON.parse source text access (JSON.rawJSON, JSON.isRawJSON, reviver context.source for exact big numbers).using/await using, Symbol.dispose/asyncDispose, DisposableStack), Temporal, joint iteration (Iterator.zip, zipKeyed), Atomics.pause. Shipping in engines ahead of the spec year.import defer, import source/source phase imports, Intl.DurationFormat (shipped broadly), and the Signals proposal at stage 1 as the cross-framework reactivity primitive.build.target is 'baseline-widely-available' (since Vite 7), so the build transpiles syntax below that line and leaves newer runtime APIs to polyfills.using, decorators, class fields) but cannot add runtime APIs (Iterator.concat, Map.getOrInsert); those need polyfills (core-js) or a runtime check. Node's version fixes what the server has; the browser list fixes what the client has.lib (es2026) and downlevels syntax by target, but a lib entry does not make the API exist in an old browser.Array.prototype.sort stable since ES2019, optional catch binding, ??=/||=/&&=, top-level await (ES2022), class static blocks and #private (ES2022), Object.hasOwn, at(), structuredClone (web API, not ECMAScript), Error cause option.ES2026 in one file:
// Upsert: no more has/set dance
const groups = new Map<string, string[]>()
for (const user of users) groups.getOrInsertComputed(user.team, () => []).push(user.name)
// Iterator sequencing
const everything = Iterator.concat(activeUsers, invitedUsers).map(u => u.email).toArray()
// Binary <-> base64/hex without btoa hacks
const bytes = new TextEncoder().encode('héllo')
const b64 = bytes.toBase64() // 'aMOpbGxv'
const back = Uint8Array.fromBase64(b64)
// Exact summation of doubles: [0.1, 0.2, 0.3].reduce(...) is 0.6000000000000001
Math.sumPrecise([0.1, 0.2, 0.3]) // 0.6
// Cross-realm safe error check
Error.isError(caught)
// Collect an async iterable
const rows = await Array.fromAsync(readLines(file))
// Big numbers survive JSON round-trips via source text access
const parsed = JSON.parse('{"id": 9007199254740993}', (key, value, context) =>
key === 'id' ? BigInt(context.source) : value)
JSON.stringify({ id: JSON.rawJSON('9007199254740993') }) // '{"id":9007199254740993}'
ES2027's headliners, already usable through TypeScript downlevelling or polyfills:
// Explicit Resource Management: dispose in reverse order at block exit, even on throw
{
using conn = await pool.connect() // conn[Symbol.asyncDispose] or [Symbol.dispose]
using tx = conn.begin()
await tx.run(query)
} // tx disposed, then conn released
// Temporal: no more Date arithmetic bugs
const start = Temporal.PlainDate.from('2026-09-21')
const due = start.add({ weeks: 2 }) // 2026-10-05, calendar-aware
const zoned = Temporal.ZonedDateTime.from('2026-09-21T10:00[Europe/Prague]')
zoned.withTimeZone('America/New_York').toString()
// Joint iteration
for (const [name, score] of Iterator.zip([names, scores])) console.log(name, score)
Deciding what to ship, in configuration:
export default defineNuxtConfig({
vite: {
build: { target: 'baseline-widely-available' }, // syntax below this line is downlevelled by Oxc/esbuild
},
nitro: { esbuild: { options: { target: 'node24' } } }, // the server's Node fixes what it can run
})
// Runtime APIs need polyfills, not transpiling. Load only when missing.
export default defineNuxtPlugin(async () => {
if (!('getOrInsert' in Map.prototype)) await import('core-js/actual/map/get-or-insert')
if (!('toBase64' in Uint8Array.prototype)) await import('core-js/actual/typed-array/to-base64')
})
TypeScript with lib: ['es2026'] happily type-checks map.getOrInsert(), and esbuild passes it through untouched because it is an API, not syntax. On a browser two versions behind, that is a TypeError in production. Check Baseline status (or caniuse) for APIs and let the build target handle syntax.
Temporal reached stage 4 with an ES2027 publication year and ships in Firefox and behind flags or partially elsewhere; production use in 2026 means the polyfill (temporal-polyfill) and a bundle-size decision. Say "finished proposal, shipping progressively" rather than "part of ES2026".
The exact ES2026 list and the ES2027 pipeline (Explicit Resource Management, Temporal, Joint Iteration, Atomics.pause), plus browser Baseline status of Temporal and using as of the interview week.
erasableSyntaxOnly-friendly TypeScript settings and write a using block with a DisposableStack; check what the emitted JavaScript looks like at target: es2022."ES2024 brought Promise.withResolvers, Object.groupBy, resizable ArrayBuffers and the RegExp v flag. ES2025 added Set algebra methods, iterator helpers, RegExp.escape, Promise.try, JSON modules with import attributes and Float16Array. ES2026, ratified this June, added Map upsert with getOrInsert, Iterator.concat, base64 and hex on Uint8Array, Math.sumPrecise, Error.isError, Array.fromAsync and JSON source-text access for exact big numbers. Already finished for 2027 are Explicit Resource Management with using, Temporal and joint iteration. In practice I decide by Baseline status: syntax is downlevelled by the build target, runtime APIs need polyfills until they are widely available."
Nothing yet. Notes filed here show up on this page and the section overview.
Memory and performance in JavaScript
How garbage collection decides what lives, the leak patterns that survive it, finding retainers with heap snapshots, and the performance model — Big-O in practice, hot paths, long tasks, and measuring before optimising.
Dates, numbers and Intl
Why Date is a trap and how to store and format time correctly across server and client, Temporal, the Intl formatters for dates, numbers, currencies, plurals, lists and relative time, floating point and money, and caching formatters.