JavaScript · ES2021

ES12 Interactive Hub — ECMAScript 2021

Logical assignment (||= &&= ??=), String.replaceAll, Promise.any, numeric separators, WeakRef + FinalizationRegistry — syntax refinements + advanced memory management.

Experience
0 XP
Course completion0%

Logical assignment (||=, &&=, ??=)

Core topic

Medium5 min

💡 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 (old style)Verbose / clunky
// 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 (Modern)Optimal & recommended
// 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;
}
Got it down? Try running real code or take the quiz!

ES12 Quick Reference

Quick syntax overview + copy snippets

Logical assignment (||=, &&=, ??=)

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)
...
String.replaceAll

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";
...
Promise.any

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'),
...
Numeric separator (_)

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;
...
WeakRef & FinalizationRegistry

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>
...