Optional Chaining & Nullish Coalescing

Optional chaining ( ?. ) safely reads deeply nested values without crashing on missing data, and nullish coalescing ( ?? ) supplies a fallback only when a value is null or undefined .

Learn Optional Chaining & Nullish Coalescing in our free JavaScript course — an interactive lesson with runnable examples, a practice exercise and a quick…

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Together they replace long a && a.b && a.b.c guards and buggy || defaults with two tiny, precise operators.

📚 Prerequisites: You should understand objects, arrays, and the idea of truthy and falsy values . These operators are all about handling null and undefined gracefully.

🔗 Real-World Analogy: Optional chaining is like a cautious tour guide :

Reading user.address.city throws if address is missing. Optional chaining fixes that: user.address?.city stops and returns undefined the moment a link in the chain is null or undefined . This short-circuiting is the whole point — it never even evaluates what comes after the missing piece.

Only place ?. where data might be missing. If you know user always exists, write user.address?.city — over-using ?. can hide real bugs.

The same idea works for methods and array indexing. Use obj.method?.() to call a method only if it exists — perfect for optional callbacks. Use arr?.[i] to index only when the array is actually there. If the thing isn't callable or indexable, you get undefined rather than a crash.

Note the syntax: for calls and indexes the ?. comes before the parentheses or brackets — fn?.() and arr?.[0] , not fn()?. .

Optional chaining gives you undefined when data is missing — and ?? turns that into a sensible default. The crucial difference from || : ?? only falls back for null and undefined , while || also falls back for 0 , "" , and false . That distinction prevents a very common bug. The ??= operator assigns a default only when the target is nullish.

Pairs beautifully: const city = user?.address?.city ?? "Unknown"; reads safely AND provides a clean default in a single, readable line.

Read city safely and fall back to "Unknown" if it's missing.

Predict the output before revealing the answer.

An empty string — ?? only replaces null / undefined , and "" is neither.

fallback — || falls back on any falsy value, and "" is falsy.

undefined — the chain short-circuits at the very first null .

Read deeply nested settings safely and apply sensible defaults that keep valid 0 values.

Up next: Essential Array Methods — find, some, every, flat, and the new immutable ones. 🧰

Practice quiz

What does optional chaining (?.) return when a link in the chain is null or undefined?

  • null
  • An error is thrown
  • undefined
  • false

Answer: undefined. ?. short-circuits and evaluates to undefined instead of throwing a 'cannot read property' error.

Given ghost = { name: 'Nobody' } (no address), what does ghost?.address?.city return?

  • undefined
  • null
  • ''
  • It throws

Answer: undefined. The chain short-circuits at the missing address and returns undefined safely.

What is the difference between ?? and ||?

  • They are identical
  • || falls back only for null/undefined
  • ?? falls back for any falsy value
  • ?? falls back only for null/undefined; || falls back for any falsy value

Answer: ?? falls back only for null/undefined; || falls back for any falsy value. ?? only replaces null/undefined, while || also replaces 0, '', and false.

What does const count = 0; count ?? 10 evaluate to?

  • 10
  • 0
  • undefined
  • null

Answer: 0. 0 is not null or undefined, so ?? keeps it, giving 0 (unlike || which would give 10).

What does '' ?? 'fallback' evaluate to?

  • An empty string
  • 'fallback'
  • undefined
  • null

Answer: An empty string. ?? only replaces null/undefined; an empty string is neither, so it is kept.

What does '' || 'fallback' evaluate to?

  • An empty string
  • undefined
  • 'fallback'
  • false

Answer: 'fallback'. || falls back on any falsy value, and '' is falsy, so it returns 'fallback'.

How do you safely call a method only if it exists?

  • obj.method()?.
  • obj.method?.()
  • obj?.method()
  • obj.method!.()

Answer: obj.method?.(). For optional calls, ?. comes before the parentheses: obj.method?.().

What does ??= do?

  • Always reassigns the variable
  • Compares two values
  • Deletes the property
  • Assigns the value only if the target is currently null or undefined

Answer: Assigns the value only if the target is currently null or undefined. Nullish assignment x ??= y sets y only when x is null or undefined.

What is the result of const o = null; o?.x?.y?

  • null
  • undefined
  • An error
  • 0

Answer: undefined. The chain short-circuits at the very first null and returns undefined.

Why can a?.b.c still throw even though it uses optional chaining?

  • ?. doesn't work on objects
  • It never throws
  • If a.b is missing, the non-optional .c still throws — guard every link with a?.b?.c
  • c must be a function

Answer: If a.b is missing, the non-optional .c still throws — guard every link with a?.b?.c. ?. only guards the link it is attached to; you must write a?.b?.c to guard every possibly-missing link.