Skip to content
Go back

ES2026 Features You Should Know

ES2026 Features You Should Know

ES2026 brings a wave of practical improvements to JavaScript. From date handling to set operations, lazy iterators to typed arrays, these features address long-standing pain points. Let’s explore each one.


1. Temporal API: Finally, Dates Done Right

JavaScript’s Date object has been a pain point since 1995. The Temporal API, arriving in ES2026, provides a modern, intuitive API for date and time operations.

The Problem with Date

// The old way - confusing and error-prone
const date = new Date(2026, 3, 5); // April 5, 2026 (months are 0-indexed!)
const month = date.getMonth(); // 3 (April, but returns 3)
const day = date.getDate(); // 5

// Timezone issues
const now = new Date();
const hours = now.getHours(); // Depends on local timezone

The New Way with Temporal

// Clear and explicit
const date = Temporal.PlainDate.from("2026-04-05");
const month = date.month; // 4 (April)
const day = date.day; // 5
const dayOfWeek = date.dayOfWeek; // 7 (Sunday, 1-indexed)

Core Temporal Types

PlainDate - Date without time or timezone:

const date = Temporal.PlainDate.from("2026-04-05");
const date2 = Temporal.PlainDate.from({ year: 2026, month: 4, day: 5 });

date.year; // 2026
date.month; // 4
date.day; // 5
date.dayOfWeek; // 7 (Sunday)
date.dayOfYear; // 95

PlainTime - Time without date:

const time = Temporal.PlainTime.from("14:30:00");
time.hour; // 14
time.minute; // 30

ZonedDateTime - Full date, time, and timezone:

const zdt = Temporal.ZonedDateTime.from("2026-04-05T14:30:00[Europe/Madrid]");
zdt.timeZone; // Europe/Madrid
zdt.offset; // +02:00

Date Arithmetic

const date = Temporal.PlainDate.from("2026-04-05");

const tomorrow = date.add({ days: 1 });
const nextMonth = date.add({ months: 1 });
const yesterday = date.subtract({ days: 1 });

const date1 = Temporal.PlainDate.from("2026-04-05");
const date2 = Temporal.PlainDate.from("2026-04-10");
const diff = date1.until(date2);
diff.days; // 5

Timezone Handling

const now = Temporal.Now.zonedDateTime("Europe/Madrid");
const ny = now.withTimeZone("America/New_York");

const madrid = Temporal.ZonedDateTime.from("2026-04-05T14:30[Europe/Madrid]");
const ny = madrid.withTimeZone("America/New_York");
ny.toString(); // '2026-04-05T08:30:00-04:00[America/New_York]'

Migration from Date

// Old
const legacy = new Date();
const iso = legacy.toISOString();

// New
const temporal = Temporal.Now.zonedDateTime("UTC");
const iso = temporal.toString();

// Converting between them
const legacy = new Date();
const temporal = Temporal.Instant.fromEpochMilliseconds(legacy.getTime());

Polyfill

npm install @js-temporal/polyfill
import "@js-temporal/polyfill";
// Temporal is now available globally

2. Iterator Helpers: Lazy Evaluation Without Intermediate Arrays

Processing iterators traditionally required converting to arrays first. ES2026 Iterator Helpers bring array methods directly to iterators, enabling efficient lazy evaluation.

The Problem

// Without Iterator Helpers - creates intermediate arrays
function* numbers() {
  for (let i = 0; i < 1000000; i++) {
    yield i;
  }
}

const result = [...numbers()] // Creates array of 1M elements
  .filter(n => n % 2 === 0) // Creates another array
  .map(n => n * 2) // Creates another array
  .slice(0, 10); // Creates final array

This wastes memory creating unnecessary intermediate arrays.

The Solution

// With Iterator Helpers - lazy evaluation
const result = numbers()
  .filter(n => n % 2 === 0)
  .map(n => n * 2)
  .take(10)
  .toArray();

No intermediate arrays. Values are computed only when needed.

Available Methods

MethodDescription
map()Transform each element
filter()Keep elements matching a predicate
take(n)Take first n elements
drop(n)Skip first n elements
flatMap()Map and flatten in one step
reduce()Reduce to single value
toArray()Convert iterator to array
forEach()Iterate without creating array
some()Check if any element matches
every()Check if all elements match
find()Find first matching element

Real-World Examples

Processing Large Files:

function* readLines(file) {
  yield* file.split("\n");
}

const result = readLines(largeFile)
  .filter(line => line.includes("error"))
  .map(line => line.substring(0, 100))
  .take(100)
  .toArray();

Infinite Sequences:

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const first10EvenFibs = fibonacci()
  .filter(n => n % 2 === 0)
  .take(10)
  .toArray();
// [0, 2, 8, 34, 144, 610, 2584, 10946, 46368, 196418]

Method Chaining:

const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  .values()
  .filter(x => x % 2 === 0) // [2, 4, 6, 8, 10]
  .map(x => x * 3) // [6, 12, 18, 24, 30]
  .drop(1) // [12, 18, 24, 30]
  .take(3) // [12, 18, 24]
  .reduce((a, b) => a + b, 0); // 54

3. Set Methods: Native Set Operations

Set operations have long required custom implementations or libraries. ES2026 adds native methods for intersection, union, difference, and more directly to the Set prototype.

The Old Way

// Before ES2026 - manual implementations
function intersection(setA, setB) {
  return new Set([...setA].filter(x => setB.has(x)));
}

function union(setA, setB) {
  return new Set([...setA, ...setB]);
}

ES2026 Set Methods

MethodReturnsDescription
intersection(other)SetElements in both sets
union(other)SetElements in either set
difference(other)SetElements in first, not second
symmetricDifference(other)SetElements in either, not both
isSubsetOf(other)BooleanAll elements in other set
isSupersetOf(other)BooleanContains all of other set
isDisjointFrom(other)BooleanNo common elements
equals(other)BooleanSame elements

Examples

Finding Common Tags:

const article1Tags = new Set(["javascript", "css", "web"]);
const article2Tags = new Set(["javascript", "nodejs", "backend"]);

const commonTags = article1Tags.intersection(article2Tags);
// Set { 'javascript' }

Merging User Permissions:

const defaultPermissions = new Set(["read", "write"]);
const adminPermissions = new Set(["read", "write", "delete", "admin"]);

const userPermissions = defaultPermissions.union(adminPermissions);
// Set { 'read', 'write', 'delete', 'admin' }

Finding Unread Items:

const allEmails = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const readEmails = new Set([1, 3, 5, 7]);

const unreadEmails = allEmails.difference(readEmails);
// Set { 2, 4, 6, 8, 9, 10 }

Role-Based Access Control:

const userRoles = new Set(["editor", "viewer"]);
const requiredRoles = new Set(["admin", "editor"]);

const hasAccess = userRoles.intersection(requiredRoles).size > 0;
// true (user has 'editor')

const hasAllAccess = requiredRoles.isSubsetOf(userRoles);
// false (user doesn't have 'admin')

Chaining Operations:

const a = new Set([1, 2, 3, 4, 5]);
const b = new Set([4, 5, 6, 7, 8]);
const c = new Set([5, 6, 7, 8, 9]);

const result = a
  .union(b) // {1, 2, 3, 4, 5, 6, 7, 8}
  .intersection(c) // {5, 6, 7, 8}
  .difference(new Set([5])); // {6, 7, 8}

4. RegExp.escape: Safe String Escaping for Regex

Building regular expressions from user input has always been error-prone. ES2026’s RegExp.escape provides a standard way to escape special characters.

The Problem

// Dangerous: unescaped user input in regex
function findWord(text, word) {
  const regex = new RegExp(word, "gi");
  return text.match(regex);
}

findWord("The price is $10", "$10"); // Error: Invalid regex

The Solution

const escaped = RegExp.escape("price: $10 (50% off)");
// 'price: \\$10 \\(50% off\\)'

const regex = new RegExp(escaped, "gi");

Practical Examples

Search Highlighting:

function highlight(text, query) {
  const escaped = RegExp.escape(query);
  const regex = new RegExp(`(${escaped})`, "gi");
  return text.replace(regex, "<mark>$1</mark>");
}

highlight("The price is $10", "$10");
// 'The price is <mark>$10</mark>'

Building Complex Regex:

const prefix = "https://example.com/";
const path = "search?q=test&page=1";

const escapedPrefix = RegExp.escape(prefix);
const escapedPath = RegExp.escape(path);

const regex = new RegExp(`^${escapedPrefix}${escapedPath}$`);
regex.test("https://example.com/search?q=test&page=1"); // true

User-Configurable Filters:

function createFilter(bannedWords) {
  const escaped = bannedWords.map(w => RegExp.escape(w));
  const pattern = escaped.join("|");
  return new RegExp(`\\b(${pattern})\\b`, "gi");
}

const filter = createFilter(["$spam", "free$$", "click.here"]);
const text = "Avoid $spam and free$$ offers";
const matches = text.match(filter);
// ['$spam', 'free$$']

What Gets Escaped

CharacterEscaped To
.\\.
*\\*
+\\+
?\\?
^\\^
$\\$
{ }\\{ \\}
( )\\( \\)
[ ]\\[ \\]
/\\/
\\\\\

Libraries Replaced

// lodash
import escapeRegExp from "lodash/escapeRegExp";

// escape-string-regexp package
import escapeStringRegexp from "escape-string-regexp";

// Now built-in
const escaped = RegExp.escape(string);

5. Float16Array: 16-bit Floats for ML and Graphics

JavaScript’s typed arrays now include Float16Array, a 16-bit floating point format optimized for machine learning and graphics workloads.

Why Float16?

TypeBytesPrecisionUse Case
Float648HighScientific computing
Float324MediumGraphics, audio
Float162LowML, GPU textures

Float16 halves memory compared to Float32, crucial for large ML models.

Usage

// Create from values
const arr = new Float16Array([1.5, 2.7, 3.14159]);
// Float16Array(3) [1.5, 2.7, 3.140625]

// Create with size
const buffer = new Float16Array(1000); // 2000 bytes

// From another typed array
const float32 = new Float32Array([1.0, 2.0, 3.0]);
const float16 = new Float16Array(float32);

Memory Comparison

const size = 10000000; // 10 million elements

const f64 = new Float64Array(size); // 80 MB
const f32 = new Float32Array(size); // 40 MB
const f16 = new Float16Array(size); // 20 MB

Machine Learning Use Case

// Neural network weights (reduced memory)
const weights = new Float16Array(1000000); // 2MB vs 4MB for Float32

function forward(input, weights) {
  const hidden = new Float16Array(256);
  for (let i = 0; i < 256; i++) {
    let sum = 0;
    for (let j = 0; j < 784; j++) {
      sum += input[j] * weights[i * 784 + j];
    }
    hidden[i] = Math.max(0, sum); // ReLU activation
  }
  return hidden;
}

Precision Tradeoffs

const arr = new Float16Array([3.141592653589793]);
arr[0]; // 3.140625 (precision lost)

// Large numbers overflow
const big = new Float16Array([100000]);
big[0]; // Infinity (exceeds max ~65504)
PropertyFloat16Float32
Max value~65,504~3.4e38
Min positive~6.1e-5~1.2e-38
Decimal digits~3-4~7

Browser Support

All ES2026 features are standardized and will be supported by:

BrowserStatus
ChromeES2026
FirefoxES2026
SafariES2026
EdgeES2026

For earlier browser support, use the respective polyfills:

npm install @js-temporal/polyfill  # For Temporal API

Summary

FeatureProblem SolvedKey Benefit
Temporal APIDate handling painImmutable, timezone-aware dates
Iterator HelpersIntermediate arraysLazy evaluation, memory efficient
Set MethodsManual set operationsNative intersection, union, difference
RegExp.escapeUnsafe regex constructionNo more copy-paste escape functions
Float16ArrayML memory overheadHalf the memory for ML models

Each of these features addresses a real pain point. Together, they make JavaScript more expressive, efficient, and safer.


Share this post on:

Previous Post
OpenClaw + llama.cpp: Your Local AI Assistant, Zero Cloud Dependency
Next Post
Astro 6 - Major Update with Node.js 22+ Requirement