JavaScript continues to evolve. This chapter covers important features from ES2020 through ES2024 that every advanced developer should know.

Optional Chaining (?.)

Safely access nested properties:

  let user = { profile: { name: 'Alice' } };

console.log(user?.profile?.name);  // 'Alice'
console.log(user?.address?.city); // undefined (no error)

let fn = user?.greet?.();         // undefined if greet doesn't exist
  

Nullish Coalescing (??)

Default only for null or undefined:

  let count = 0;
console.log(count || 10);  // 10 — wrong if 0 is valid
console.log(count ?? 10);  // 0  — correct
  

Logical Assignment

  let a = null;
a ??= 'default';  // a = 'default'
a ||= 'other';    // a stays 'default' (truthy)
a &&= false;      // a = false
  

Private Class Fields (#)

  class BankAccount {
    #balance = 0;

    deposit(amount) {
        this.#balance += amount;
    }

    getBalance() {
        return this.#balance;
    }
}

const account = new BankAccount();
// account.#balance; // SyntaxError — private
  

Static Class Fields and Blocks

  class Config {
    static API_URL = 'https://api.example.com';
    static {
        // static initialization block
        this.TIMEOUT = 5000;
    }
}
  

Top-Level await (Modules)

  // app.js (ES module)
const config = await fetch('/config.json').then(r => r.json());
console.log(config);
  

Promise.allSettled

Wait for all promises regardless of outcome:

  const results = await Promise.allSettled([
    fetch('/api/a'),
    fetch('/api/b'),
    Promise.reject('fail')
]);

results.forEach(r => {
    if (r.status === 'fulfilled') console.log(r.value);
    else console.log(r.reason);
});
  

String.prototype.replaceAll

  'a-b-c'.replaceAll('-', '_'); // 'a_b_c'
  

Array.at()

Negative indexing:

  [1, 2, 3].at(-1); // 3
[1, 2, 3].at(0);  // 1
  

Object.hasOwn()

Safer than obj.hasOwnProperty():

  Object.hasOwn({ a: 1 }, 'a');        // true
Object.hasOwn({ a: 1 }, 'toString'); // false
  

Structured Clone

Deep clone supported types (including Date, Map, Set):

  const original = { date: new Date(), map: new Map([[1, 2]]) };
const copy = structuredClone(original);
  

Temporal (Stage 3 — future)

Replacing the problematic Date API. Check tc39 proposals for current status.

RegExp match indices

  const re = /(\d+)/d;
const match = re.exec('test123');
console.log(match.indices[0]); // [4, 7]
  

Stay current by checking MDN JavaScript reference and Can I use for browser support.