What New ECMAScript Proposals Will Shape JavaScript in 2023?
This article reviews the latest Stage 4 ECMAScript proposals—including ArrayBuffer transfer, iterator helpers, RegExp modifiers, import attributes, Promise.try, duplicate named capture groups, and Set methods—explaining their purpose, syntax, and example usage for modern JavaScript development.
When a proposal reaches Stage 4, it means it can be tried in multiple browsers and Node.js, and it will be incorporated into the next annual ECMAScript release such as ECMAScript 2023.
ArrayBuffer transfer
Proposal address: proposal-arraybuffer-transfer
This proposal adds two new methods to the
ArrayBufferprototype:
ArrayBuffer.transferand
ArrayBuffer.transferToFixedLength, providing the ability to transfer buffer ownership.
When we need to read/write a buffer, external writes must be prevented:
<code>function validateAndWrite(arrayBuffer) {
// Do some asynchronous validation.
await validate(arrayBuffer);
// Assuming we have reached here, it's valid; write it to disk.
await fs.writeFile("data.bin", arrayBuffer);
}
const data = new Uint8Array([0x01, 0x02, 0x03]);
validateAndWrite(data.buffer);
setTimeout(() => {
data[0] = data[1] = data[2] = 0x00;
}, 50);
</code>Because the execution time of
validate(arrayBuffer)may cause the buffer content to expire, a defensive approach copies the buffer before validation:
<code>function validateAndWriteSafeButSlow(arrayBuffer) {
// Copy first!
const copy = arrayBuffer.slice();
await validate(copy);
await fs.writeFile("data.bin", copy);
}
</code>However, this traditional method can be slow. Using
transferenables zero‑copy ownership transfer for better performance:
<code>function validateAndWriteSafeAndFast(arrayBuffer) {
// Transfer to take ownership, which implementations can choose to implement as a zero-copy move.
const owned = arrayBuffer.transfer();
// arrayBuffer is detached after this point.
assert(arrayBuffer.detached);
await validate(owned);
await fs.writeFile("data.bin", owned);
}
</code>Sync Iterator Helpers
Proposal address: proposal-iterator-helpers
This proposal adds convenient methods to iterator objects, such as
map,
filter,
flatMap,
reduce,
forEach, and
some, plus several RxJS‑like helpers.
.take(limit)
Limits the number of generated elements and returns a new iterator.
<code>function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
}
const result = naturals()
.take(3);
result.next(); // {value: 0, done: false}
result.next(); // {value: 1, done: false}
result.next(); // {value: 2, done: false}
result.next(); // {value: undefined, done: true}
</code>.drop(limit)
Skips the specified number of elements and returns a new iterator.
<code>function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
}
const result = naturals()
.drop(3);
result.next(); // {value: 3, done: false}
result.next(); // {value: 4, done: false}
result.next(); // {value: 5, done: false}
</code>.flatMap(mapperFn)
Expands or flattens nested structures and returns a new iterator.
<code>const sunny = ["It's Sunny in", "", "California"].values();
const result = sunny
.flatMap(value => value.split(" ").values());
result.next(); // {value: "It's", done: false}
result.next(); // {value: "Sunny", done: false}
result.next(); // {value: "in", done: false}
result.next(); // {value: "", done: false}
result.next(); // {value: "California", done: false}
result.next(); // {value: undefined, done: true}
</code>.toArray()
Converts the values produced by an iterator into an array.
<code>function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
}
const result = naturals()
.take(5)
.toArray();
result // [0, 1, 2, 3, 4]
</code>RegExp Modifiers
Most regex engines (Perl, PCRE, .NET, Oniguruma) allow controlling flags inside sub‑expressions, but ECMAScript lacks this capability. This proposal introduces regex pattern modifiers to flexibly control flags such as
i(ignore case),
m(multiline),
s(dot‑all), and
x(extended).
Modifier syntax:
(?imsx-imsx:subexpression)– set or unset the listed flags for the subexpression.
(?imsx-imsx)– set or unset flags from the current position to the next
)or end of pattern.
<code>const re1 = /^[a-z](?-i:[a-z] "a-z")$/i;
re1.test("ab"); // true
re1.test("Ab"); // true
re1.test("aB"); // false
const re2 = /^(?i:[a-z])[a-z]$/;
re2.test("ab"); // true
re2.test("Ab"); // true
re2.test("aB"); // false
</code>Import Attributes and JSON Modules
Proposal address: proposal-import-attributes
This proposal adds inline syntax to import statements so that additional information can be passed with the module specifier, enabling generic support for new module types.
Example for importing a JSON module:
<code>// static import
import json from "./foo.json" with { type: "json" };
// dynamic import
import("foo.json", { with: { type: "json" } });
</code>The proposal also supports inline syntax for re‑exports:
<code>export { val } from './foo.js' with { type: "javascript" };
</code>Different host environments (Node.js, web) provide various ways to load modules; import attributes can convey these differences, even in HTML via script tag attributes.
<code><script src="foo.wasm" type="module" withtype="webassembly"></script>
</code>Promise.try
Proposal address: proposal-promise-try
While
.catchhandles errors in a Promise chain, the initial synchronous call (e.g.,
queryUser(id)) is not captured. The
Promise.trymethod wraps the starting call in a resolved Promise, extending error handling to synchronous failures.
<code>import pTry from 'p-try';
function processUser(id) {
return pTry(queryUser, id)
.then(user => queryAccount(user))
.then(account => queryAuth(account))
.catch(() => { /* ... */ });
}
</code>Duplicate Named Capture Groups
Proposal address: proposal-duplicated-named-capturing-groups
Current ECMAScript requires capture group names to be unique, preventing their use in alternations such as
YYYY‑MM‑DD|DD‑MM‑YYYY. This proposal allows non‑unique names to enable such patterns.
Set Methods
Proposal address: proposal-set-methods
This proposal adds a suite of built‑in methods to
Setfor common set operations:
intersection,
union,
difference,
symmetricDifference,
isSubsetOf,
isSupersetOf, and
isDisjointFrom. Each method accepts another
Set(or an object implementing
.size,
.keys, and
.has).
References
proposal-arraybuffer-transfer: https://github.com/tc39/proposal-arraybuffer-transfer
proposal-iterator-helpers: https://github.com/tc39/proposal-iterator-helpers
Regular Expression X Mode: https://github.com/rbuckton/proposal-regexp-x-mode
proposal-import-attributes: https://github.com/tc39/proposal-import-attributes
proposal-promise-try: https://github.com/tc39/proposal-promise-try
p-try: https://www.npmjs.com/package/p-try
proposal-duplicate-named-capturing-groups: https://github.com/tc39/proposal-duplicate-named-capturing-groups
proposal-set-methods: https://github.com/tc39/proposal-set-methods
Taobao Frontend Technology
The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.