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') falseDuplicate 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:
- Math.f16round()
- New element type for the Typed Arrays API:
- Float16Array
- DataView.prototype.getFloat16()
- DataView.prototype.setFloat16()
Free book on ECMAScript 2025
My book “Exploring JavaScript (ES2025 Edition)” is free to read online. Two chapters are especially relevant:
- “History and evolution of JavaScript”: ECMAScript vs. JavaScript, TC39, TC39 process, ECMAScript proposals, etc.
- “New JavaScript features”: What are the new features of each ECMAScript version?
.png)


