ES12 Interactive Hub — ECMAScript 2021
Logical assignment (||= &&= ??=), String.replaceAll, Promise.any, numeric separators, WeakRef + FinalizationRegistry — syntax refinements + advanced memory management.
Logical assignment (||=, &&=, ??=)
Core topic
💡 Concept summary
Combines a logical operator with assignment — write x ??= y instead of x = x ?? y, which is shorter and more efficient.
🤔 Why do you need this feature?
The "if value is falsy/nullish then set default" pattern is very common, but the x = x || y syntax is long and re-evaluates x. Logical assignment only assigns when needed, which is semantically more optimal.
// Before ES12 — old-style default assignment
var x = null;
x = x || 10; // x = 10 (but 0/'' get replaced too)
x = x !== null && x !== undefined ? x : 10; // correct but long
// Common pattern
function setDefault(opts) {
opts.theme = opts.theme || 'light';
opts.retries = opts.retries === undefined ? 3 : opts.retries;
return opts;
}// ES12 — 3 new operators
let x = null;
x ??= 10; // x = 10 (because null/undefined)
x ??= 20; // x is still = 10 (no assignment)
let y = 0;
y ||= 5; // y = 5 (0 is falsy)
let cfg = { a: 1, b: 'ok' };
cfg.b &&= cfg.b.toUpperCase(); // only assign when b is truthy
console.log(cfg); // { a: 1, b: 'OK' }
// The set-default pattern is now extremely concise
function setDefault(opts) {
opts.theme ??= 'light';
opts.retries ??= 3;
return opts;
}ES12 Quick Reference
Quick syntax overview + copy snippets
Combines a logical operator with assignment — write x ??= y instead of x = x ?? y, which is shorter and more efficient.
let x = null; x ??= 10; // x = 10 (because null/undefined) x ??= 20; // x is still = 10 (no assignment) ...
A method that replaces ALL occurrences of a string without needing a global regex.
const str = "a-b-c-d";
console.log(str.replaceAll('-', '_')); // 'a_b_c_d'
const s = "1.2.3";
...Resolves when the FIRST promise succeeds. It only rejects (with an AggregateError) when ALL promises fail.
try {
const data = await Promise.any([
fetch('https://cdn1.../data'),
...Allows using the underscore "_" as a separator inside number literals for readability — WITHOUT affecting the value.
const billion = 1_000_000_000; const bytes = 0xFF_FF_FF_FF; const binary = 0b1010_0001_1000_0101; ...
An advanced memory-management duo: WeakRef is a WEAK reference (does not prevent GC), and FinalizationRegistry runs a callback after an object is garbage-collected.
class WeakCache {
constructor() {
this.map = new Map(); // key → WeakRef<value>
...