Ecma International approves ECMAScript 2025: What's new?

4 months ago 5

On 25 June 2025, the 129th Ecma General Assembly approved the ECMAScript 2025 language specification (press release), which means that it’s officially a standard now.

This blog post explains what’s new.

The editors of ECMAScript 2025  

The editors of this release are:

  • Shu-yu Guo
  • Michael Ficarra
  • Kevin Gibbons

What’s new in ECMAScript 2025?  

Import attributes and JSON modules  

Import attributes provide the syntactic foundation for importing non-JavaScript artifacts. The first such artifacts to be supported are JSON modules:

import configData1 from './config-data.json' with { type: 'json' }; const configData2 = await import( './config-data.json', { with: { type: 'json' } } );

The object literal syntax after with is used for specifying import attributes. type is an import attribute.

Iterator helper methods  

Iterator helper methods let us do more with iterators:

const arr = ['a', '', 'b', '', 'c', '', 'd', '', 'e']; assert.deepEqual( arr.values() .filter(x => x.length > 0) .drop(1) .take(3) .map(x => `=${x}=`) .toArray() , ['=b=', '=c=', '=d='] );

Some of the iterator helper methods work like the Array methods with the same names:

  • Methods that return iterators:
    • iterator.filter(filterFn)
    • iterator.map(mapFn)
    • iterator.flatMap(mapFn)
  • Methods that return booleans:
    • iterator.some(fn)
    • iterator.every(fn)
  • Methods that return other values:
    • iterator.find(fn)
    • iterator.reduce(reducer, initialValue?)
  • Methods that return no values:
    • iterator.forEach(fn)

Other iterator helper methods are unique to iterators:

  • iterator.drop(limit)
    • Returns an iterator without the first limit elements of iterator.
  • iterator.take(limit)
    • Returns an iterator with the first limit elements of iterator.
  • iterator.toArray()
    • Collects all remaining elements of iterator in an Array and returns it.

How are iterator methods an improvement over Arrays methods?  

  • Iterator methods can be used with any iterable data structure – e.g., they let us filter and map the data structures Set and Map.
  • Iterator methods don’t create intermediate Arrays and compute data incrementally. That is useful for large amounts of data:
    • With iterator methods, all methods are applied to the first value, then to the second value, etc.
    • With Array methods, the first method is applied to all values, then the second method is applied to all results, etc.

New Set methods  

There are several new Set methods:

  • Combining Sets:
    • Set.prototype.intersection(other)
    • Set.prototype.union(other)
    • Set.prototype.difference(other)
    • Set.prototype.symmetricDifference(other)
  • Checking Set relationships:
    • Set.prototype.isSubsetOf(other)
    • Set.prototype.isSupersetOf(other)
    • Set.prototype.isDisjointFrom(other)

Examples:

assert.deepEqual( new Set(['a', 'b', 'c']).union(new Set(['b', 'c', 'd'])), new Set(['a', 'b', 'c', 'd']) ); assert.deepEqual( new Set(['a', 'b', 'c']).intersection(new Set(['b', 'c', 'd'])), new Set(['b', 'c']) ); assert.deepEqual( new Set(['a', 'b']).isSubsetOf(new Set(['a', 'b', 'c'])), true ); assert.deepEqual( new Set(['a', 'b', 'c']).isSupersetOf(new Set(['a', 'b'])), true );

RegExp.escape()  

RegExp.escape() escapes text so that it can be used inside a regular expression – e.g., the following code removes all occurrences of text inside str that are not quoted:

function removeUnquotedText(str, text) { const regExp = new RegExp( `(?<!“)${RegExp.escape(text)}(?!”)`, 'gu' ); return str.replaceAll(regExp, '•'); } assert.equal( removeUnquotedText('“yes” and yes and “yes”', 'yes'), '“yes” and • and “yes”' );

Regular expression pattern modifiers (inline flags)  

Regular expression pattern modifiers (inline flags) let us apply flags to parts of a regular expression (vs. all of the regular expression) – for example, in the following regular expression, the flag i is only applied to “HELLO”:

> /^x(?i:HELLO)x$/.test('xHELLOx') true > /^x(?i:HELLO)x$/.test('xhellox') true > /^x(?i:HELLO)x$/.test('XhelloX') false

Duplicate named capture groups  

Duplicate named capture groups: We can now use the same group name twice – as long as it appears in different alternatives:

const RE = /(?<chars>a+)|(?<chars>b+)/v; assert.deepEqual( RE.exec('aaa').groups, { chars: 'aaa', __proto__: null, } ); assert.deepEqual( RE.exec('bb').groups, { chars: 'bb', __proto__: null, } );

Promise.try()  

Promise.try() lets us start a Promise chain with code that is not purely asynchronous – e.g.:

function computeAsync() { return Promise.try(() => { const value = syncFuncMightThrow(); return asyncFunc(value); }); }

Support for 16-bit floating point numbers (float16)  

This support provides the following features:

Free book on ECMAScript 2025  

My book “Exploring JavaScript (ES2025 Edition)” is free to read online. Two chapters are especially relevant:

Read Entire Article