Some features are new enough that you should check support before relying on them. Each one below is part of the ECMAScript standard in a recent edition, but older browsers and runtimes may lack it. The pattern for all of them is the same: detect it, and have a fallback.
Promise.withResolvers (ES2024)
Creates a promise together with its resolve and reject functions, so you can settle it from outside.
if (typeof Promise.withResolvers === "function") {
const { promise, resolve } = Promise.withResolvers();
setTimeout(() => resolve("settled from outside"), 100);
promise.then(value => console.log(value)); // → settled from outside
} else {
console.log("Promise.withResolvers is not available");
}
It replaces the awkward pattern of copying resolve out of the executor function.
Set methods (ES2025)
Sets gained the operations you know from maths: union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf and isDisjointFrom.
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
if (typeof a.union === "function") {
console.log([...a.union(b)]); // → [1, 2, 3, 4]
console.log([...a.intersection(b)]); // → [2, 3]
console.log([...a.difference(b)]); // → [1]
} else {
console.log("Set methods are not available; use filter and spread instead");
}
A fallback with older tools:
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const intersection = new Set([...a].filter(x => b.has(x)));
console.log([...intersection]); // → [2, 3]
More about sets in Set and WeakSet.
Iterator helpers (ES2025)
Iterators now have map, filter, take, drop, toArray and more, so you can process an iterator lazily without building arrays first.
function* naturals() {
let n = 1;
while (true) yield n++;
}
if (typeof naturals().map === "function") {
const firstFiveSquares = naturals().map(n => n * n).take(5).toArray();
console.log(firstFiveSquares); // → [1, 4, 9, 16, 25]
} else {
console.log("Iterator helpers are not available here");
}
This works with infinite generators because each step is computed only when needed. Generators are explained in Generators.
Promise.try (ES2025)
Runs a function that may be synchronous or asynchronous, and always gives you a promise, with sync errors turned into rejections.
if (typeof Promise.try === "function") {
Promise.try(() => JSON.parse("{bad")).catch(error => console.log("caught:", error.name)); // → caught: SyntaxError
} else {
console.log("Promise.try is not available");
}
How new is “new”?
- Features in the current edition may only just have shipped in some browsers.
- Features in older editions (ES2022, ES2023) are usually safe in all current browsers, but not in very old ones.
- A feature that is still a proposal is not part of the language. Do not use it in production unless a build tool is explicitly set up to handle that proposal, and accept that its design may change.
A safe habit
- Learn the feature.
- Check MDN’s compatibility table and your audience’s browsers.
- Detect it with
typeof/inwhere it matters, and offer a fallback, or use a build step with a polyfill.