09 / 20 · Day 3
Day 3 · Concept 09

Optional chaining & nullish coalescing

foo?.bar?.baz short-circuits if any link is null/undefined. x ?? defaultValue picks the default only when x is null/undefined — not when x is 0 or "".


1 · The old way

js old.js
const data = { user: { profile: null } };

// Before optional chaining
const handle = data && data.user && data.user.profile && data.user.profile.handle;
console.log(handle);   // undefined

// Or with try/catch — even uglier
let h;
try { h = data.user.profile.handle; } catch { h = undefined; }
console.log(h);

2 · The modern way — ?.

js new.js
const data = { user: { profile: null } };

// Optional chaining
const handle = data?.user?.profile?.handle;
console.log(handle);   // undefined

// On method calls too
const onChange = obj?.callback?.(); // calls only if callback exists

// On array access
const first = arr?.[0];

The chain returns undefined at the first null/undefined link. No exceptions thrown.

3 · Nullish coalescing — ??

js nullish.js
// || picks the right side for ANY falsy value — wrong for 0 / "" / false
console.log(0 || 10);            // 10  (probably not what you wanted!)
console.log("" || "default");    // 'default'
console.log(false || true);      // true

// ?? picks the right side ONLY for null / undefined
console.log(0 ?? 10);            // 0  ✓
console.log("" ?? "default");    // ''  ✓
console.log(null ?? "fallback"); // 'fallback'
console.log(undefined ?? 42);    // 42

4 · The combo

js combo.js
function getDisplay(user) {
    return user?.profile?.displayName ?? "Anonymous";
}

console.log(getDisplay({}));                                  // Anonymous
console.log(getDisplay({ profile: { displayName: "Alice" } })); // Alice
console.log(getDisplay(null));                                 // Anonymous

Reach into a possibly-missing path; fall back to a default. The most common modern pattern.

5 · Common mistakes

  • Using || when you meant ??. const max = config.max || 100 — if config.max is 0, you get 100. Use ??.
  • Optional chaining on the LHS of assignment. obj?.x = 1 is a syntax error. Use a guard.
  • Forgetting ?.() for methods. obj?.fn() only short-circuits the ?.; if obj is null, fn() doesn't run.

6 · When it clicks

  • ?. and ?? are reflex moves on any optional data.
  • You stop writing &&-chain guards.
  • You notice || bugs in code reviews — empty strings or zeros silently replaced.
Found this useful?