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 ArrayBuffer prototype: ArrayBuffer.transfer and ArrayBuffer.transferToFixedLength, providing the ability to transfer buffer ownership.
When we need to read/write a buffer, external writes must be prevented:
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);Because the execution time of validate(arrayBuffer) may cause the buffer content to expire, a defensive approach copies the buffer before validation:
function validateAndWriteSafeButSlow(arrayBuffer) {
// Copy first!
const copy = arrayBuffer.slice();
await validate(copy);
await fs.writeFile("data.bin", copy);
}However, this traditional method can be slow. Using transfer enables zero‑copy ownership transfer for better performance:
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);
}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.
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}.drop(limit)
Skips the specified number of elements and returns a new iterator.
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}.flatMap(mapperFn)
Expands or flattens nested structures and returns a new iterator.
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}.toArray()
Converts the values produced by an iterator into an array.
function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
}
const result = naturals()
.take(5)
.toArray();
result // [0, 1, 2, 3, 4]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.
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"); // falseImport 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:
// static import
import json from "./foo.json" with { type: "json" };
// dynamic import
import("foo.json", { with: { type: "json" } });The proposal also supports inline syntax for re‑exports:
export { val } from './foo.js' with { type: "javascript" };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.
<script src="foo.wasm" type="module" withtype="webassembly"></script>Promise.try
Proposal address: proposal-promise-try
While .catch handles errors in a Promise chain, the initial synchronous call (e.g., queryUser(id)) is not captured. The Promise.try method wraps the starting call in a resolved Promise, extending error handling to synchronous failures.
import pTry from 'p-try';
function processUser(id) {
return pTry(queryUser, id)
.then(user => queryAccount(user))
.then(account => queryAuth(account))
.catch(() => { /* ... */ });
}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 Set for 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
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
