Back to blog

ECMAScript 2025: The New JavaScript Features You Need to Know

Hello HaWkers, the annual JavaScript update has arrived and brings significant changes to our favorite language. ECMAScript 2025 has been officially approved by TC39 and includes features that will transform the way we write code.

Are you ready to explore the new features that will make your code cleaner, more efficient, and expressive? Let's dive into each new feature with practical examples.

The Native Iterator Object

The main addition in ES2025 is the new Iterator object with native functional operators. This means we can now chain operations on iterators without converting to arrays.

Why This Is Revolutionary

Before, to apply transformations to iterators, we needed to convert them to arrays first, consuming unnecessary memory:

// Before (ES2024 and earlier)
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
const result = [...map.keys()]
  .filter(key => key !== 'b')
  .map(key => key.toUpperCase());
// Created intermediate array in memory

Now, with Iterator helpers:

// ES2025 - Native Iterator helpers
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
const result = map.keys()
  .filter(key => key !== 'b')
  .map(key => key.toUpperCase())
  .toArray();
// Lazy processing, no intermediate arrays

Available Iterator Methods

// All new Iterator methods
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// .map() - transforms each element
const doubled = numbers.values()
  .map(n => n * 2)
  .toArray();
// [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

// .filter() - filters elements
const evens = numbers.values()
  .filter(n => n % 2 === 0)
  .toArray();
// [2, 4, 6, 8, 10]

// .take() - takes first N elements
const firstThree = numbers.values()
  .take(3)
  .toArray();
// [1, 2, 3]

// .drop() - skips first N elements
const afterThree = numbers.values()
  .drop(3)
  .toArray();
// [4, 5, 6, 7, 8, 9, 10]

// .flatMap() - map + flatten
const nested = [[1, 2], [3, 4]];
const flat = nested.values()
  .flatMap(arr => arr.values())
  .toArray();
// [1, 2, 3, 4]

New Set Methods

ES2025 finally brings set operations that developers have been requesting for years. Now we can perform union, intersection, and difference directly on Sets.

const frontend = new Set(['React', 'Vue', 'Angular', 'Svelte']);
const popular = new Set(['React', 'Vue', 'Node', 'Express']);

// .union() - combines two sets
const allTech = frontend.union(popular);
// Set {'React', 'Vue', 'Angular', 'Svelte', 'Node', 'Express'}

// .intersection() - common elements
const frontendPopular = frontend.intersection(popular);
// Set {'React', 'Vue'}

// .difference() - elements in A but not in B
const onlyFrontend = frontend.difference(popular);
// Set {'Angular', 'Svelte'}

// .symmetricDifference() - exclusive elements from each set
const exclusive = frontend.symmetricDifference(popular);
// Set {'Angular', 'Svelte', 'Node', 'Express'}

// .isSubsetOf() - checks if subset
const react = new Set(['React']);
console.log(react.isSubsetOf(frontend)); // true

// .isSupersetOf() - checks if superset
console.log(frontend.isSupersetOf(react)); // true

// .isDisjointFrom() - checks if no intersection
const backend = new Set(['Python', 'Java', 'Go']);
console.log(frontend.isDisjointFrom(backend)); // true

Practical Application: Permission System

// Permission system with Sets
const adminPermissions = new Set(['read', 'write', 'delete', 'admin']);
const userPermissions = new Set(['read', 'write']);
const guestPermissions = new Set(['read']);

function checkAccess(userPerms, requiredPerms) {
  // Checks if user has all required permissions
  return requiredPerms.isSubsetOf(userPerms);
}

const editPagePerms = new Set(['read', 'write']);
console.log(checkAccess(adminPermissions, editPagePerms)); // true
console.log(checkAccess(guestPermissions, editPagePerms)); // false

// Find missing permissions
function missingPermissions(userPerms, requiredPerms) {
  return requiredPerms.difference(userPerms);
}

console.log(missingPermissions(guestPermissions, editPagePerms));
// Set {'write'}

Promise.try(): Simplifying Promise Chains

The new Promise.try() method solves a common problem: starting a Promise chain with code that can be synchronous or asynchronous.

// Problem before ES2025
function processData(data) {
  // Can throw synchronous error
  const parsed = JSON.parse(data);
  return fetchAdditionalData(parsed.id);
}

// Before: needed to wrap in Promise.resolve()
Promise.resolve()
  .then(() => processData(userInput))
  .then(result => console.log(result))
  .catch(err => console.error(err));

// Or use async IIFE
(async () => {
  try {
    const result = await processData(userInput);
    console.log(result);
  } catch (err) {
    console.error(err);
  }
})();

With Promise.try():

// ES2025 - Promise.try()
Promise.try(() => processData(userInput))
  .then(result => console.log(result))
  .catch(err => console.error(err));
// Catches synchronous AND asynchronous errors uniformly

Why This Matters

// Real example: configuration processing
function loadConfig(configPath) {
  // validatePath can throw synchronous error
  const validPath = validatePath(configPath);
  // readConfigFile returns Promise
  return readConfigFile(validPath);
}

// Promise.try ensures ANY error is caught
Promise.try(() => loadConfig('./config.json'))
  .then(config => initializeApp(config))
  .catch(err => {
    // Catches both validatePath and readConfigFile errors
    console.error('Failed to load config:', err);
    return loadDefaultConfig();
  });

Float16Array: New Typed Array

ES2025 adds Float16Array, a typed array for 16-bit floating-point numbers. This is especially useful for machine learning applications and graphics processing.

// Creating a Float16Array
const halfFloats = new Float16Array([1.5, 2.5, 3.5, 4.5]);
console.log(halfFloats); // Float16Array [1.5, 2.5, 3.5, 4.5]
console.log(halfFloats.BYTES_PER_ELEMENT); // 2

// Memory comparison
const float32 = new Float32Array(1000); // 4KB
const float16 = new Float16Array(1000); // 2KB
// Half the memory for the same number of elements

// Useful for WebGL and image processing
function processImageData(pixels) {
  // Normalizes pixels to 0-1 with half the memory
  const normalized = new Float16Array(pixels.length);
  for (let i = 0; i < pixels.length; i++) {
    normalized[i] = pixels[i] / 255;
  }
  return normalized;
}

Helper Functions

// New global functions for Float16
const value = 3.14159;

// Math.f16round() - rounds to 16-bit precision
const rounded = Math.f16round(value);
console.log(rounded); // 3.140625 (reduced precision)

// DataView methods for Float16
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);

view.setFloat16(0, 3.14);
console.log(view.getFloat16(0)); // 3.140625

Direct JSON Module Import

It's now possible to import JSON files directly as ES modules, without the need for fetch or require.

// ES2025 - Direct JSON import
import config from './config.json' with { type: 'json' };
import translations from './i18n/en-US.json' with { type: 'json' };

console.log(config.apiUrl);
console.log(translations.welcome);

// Dynamic import also works
const loadLocale = async (lang) => {
  const messages = await import(`./i18n/${lang}.json`, {
    with: { type: 'json' }
  });
  return messages.default;
};

Regular Expression Improvements

ES2025 brings the /v flag for regular expressions, allowing set operations in character classes.

// New /v flag for set operations
const vowels = /[aeiou]/v;
const consonants = /[a-z&&[^aeiou]]/v; // Intersection and subtraction

// Set subtraction
const lettersExceptVowels = /[[a-z]--[aeiou]]/v;
console.log(lettersExceptVowels.test('b')); // true
console.log(lettersExceptVowels.test('a')); // false

// Set union
const alphanumerics = /[[a-z][0-9]]/v;
console.log(alphanumerics.test('5')); // true
console.log(alphanumerics.test('x')); // true

// Improved Unicode support
const emoji = /\p{Emoji}/v;
console.log(emoji.test('🚀')); // true

Features Summary Table

Feature Description Use Case
Iterator Helpers Functional methods on iterators Lazy data processing
Set Methods Union, intersection, difference Set logic
Promise.try() Starts chains uniformly Error handling
Float16Array 16-bit float array ML, WebGL, games
JSON Modules Direct JSON import Config, i18n
RegExp /v flag Set operations in regex Complex validations

How to Use Today

Most modern browsers already support most of these features. For environments that don't yet support them, you can use:

// Check support
if (typeof Iterator !== 'undefined') {
  // Use native Iterator helpers
} else {
  // Fallback or polyfill
}

// Or use polyfills
// npm install core-js
import 'core-js/actual/iterator';
import 'core-js/actual/set';

Conclusion

ECMAScript 2025 represents a significant evolution of JavaScript, bringing features the community has been requesting for years. The Iterator helpers and new Set methods are particularly impactful for those working with data manipulation.

If you want to dive deeper into modern JavaScript, I recommend checking out another article: Discovering the Power of Async/Await in JavaScript where you'll discover how to master asynchronous programming.

Let's go! 🦅

Comments (0)

This article has no comments yet 😢. Be the first! 🚀🦅

Add comments