Optional chaining and ??

JavaScript · Essentials · 7 min

Real data has gaps; these operators replace long chains of && checks and buggy || defaults.

Reading a property of undefined or null throws a TypeError. Optional chaining ?. stops evaluation and returns undefined if the value on its left is null or undefined:

const city = user?.address?.city;   // undefined instead of a crash

It has three forms:

  • obj?.prop — property access
  • obj?.[expr] — bracket access
  • fn?.(args) — call only if fn exists, e.g. options.onDone?.()

The nullish coalescing operator a ?? b returns b only when a is null or undefined. Compare it with ||, which falls back on any falsy value:

const volume = settings.volume ?? 50; // keeps a valid 0
const bad = settings.volume || 50;    // 0 becomes 50!

Use ?? for defaults whenever 0, "" or false are legitimate values.

There are also logical assignment operators:

  • a ??= b — assign only if a is null/undefined
  • a ||= b — assign if a is falsy
  • a &&= b — assign if a is truthy

They're handy for filling in defaults: config.retries ??= 3.

Don't sprinkle ?. everywhere: if a value must exist, a crash with a clear error is more useful than an undefined that propagates silently. Use it where absence is genuinely expected — optional fields, API responses, optional callbacks.

One syntax note: you can't combine ?? with || or && without parentheses; a || b ?? c is a SyntaxError.

Example

const order = { id: 7, customer: { name: "Ada" }, discount: 0 };

console.log(order.customer?.name);          // "Ada"
console.log(order.shipping?.address.city);  // undefined (no crash)
console.log(order.items?.[0]);              // undefined

console.log(order.discount ?? 10);          // 0  (0 is kept)
console.log(order.discount || 10);          // 10 (0 is falsy)

const options = { onDone: undefined };
options.onDone?.();                         // no call, no error

order.notes ??= "none";
order.discount ||= 5;
console.log(order.notes, order.discount);   // none 5

Remember

  • ?. returns undefined instead of throwing when the left side is null or undefined
  • ?? defaults only for null/undefined; || also replaces 0, "" and false
  • ??=, ||=, &&= assign conditionally

Watch out for

  • Using || for a default when 0 or an empty string is a valid value.

Check yourself

  1. const n = 0; — what are n ?? 5 and n || 5?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining