Optional Chaining & Nullish Coalescing

Safely reading deeply nested properties, and providing defaults, without a pile of manual checks.

What is it?

Reading a property that's nested a few levels deep — user.address.city — crashes the whole program if user or address happens to be missing. Before modern JavaScript, safely handling that meant a chain of manual checks: if (user && user.address && user.address.city). Optional chaining (?.) does this automatically: it stops and returns undefined the moment it hits something missing, instead of throwing an error.

Its common partner, nullish coalescing (??), lets you supply a default value specifically for when something is null or undefined — without accidentally overriding valid values like 0 or "" the way || would.

Explain like I'm 10

Optional chaining is like carefully checking each door is unlocked before walking through it, instead of just barreling into a locked door and getting hurt. Nullish coalescing is a backup plan — 'if there's truly nothing here, use this instead' — that's careful not to override an answer you deliberately gave, like zero.

Examples

Optional chaining and nullish coalescing together

const user = { name: "Amara", address: null };

console.log(user.address.city);   // ❌ throws: Cannot read properties of null
console.log(user.address?.city);  // undefined — no crash

const city = user.address?.city ?? "Unknown city";
console.log(city); // "Unknown city"

const count = 0;
console.log(count || 10); // 10 — wrong! 0 is falsy, so || replaces it
console.log(count ?? 10); // 0 — right! ?? only replaces null/undefined

Optional chaining with function calls and arrays

const api = {
  getUser: null, // maybe not loaded yet
};

api.getUser?.(1);      // undefined — skipped, doesn't throw

const users = null;
console.log(users?.[0]); // undefined — safe even though users isn't an object at all

?.() guards a function call that might not exist, and ?.[...] guards array/bracket access the same way ?. guards a plain property.

How it works

?. checks whether the value immediately to its left is null or undefined before continuing; if so, the entire chain short-circuits and evaluates to undefined without attempting the rest. ?? checks only its left-hand side: if it's null or undefined, it evaluates to the right-hand side; otherwise, it keeps the left-hand value — even if that value is 0, "", or false.

Why does it exist?

Deeply nested, possibly-missing data (like optional fields from an API) used to require long chains of manual && checks just to avoid crashing. These two operators cover that extremely common need directly, making the code both safer and shorter.

When to use it

Use ?. whenever you're reading a property that might not exist at some level — optional API fields, optional configuration, DOM elements that might not be present. Use ?? whenever you want a default specifically for missing values, and your valid values might include falsy-but-real ones like 0 or "".

When not to use it

Don't sprinkle ?. everywhere defensively on data you actually know is always present — it can silently hide a bug that should have thrown an error and alerted you to a real problem. And use || instead of ?? when you genuinely want to replace any falsy value, not just null/undefined.

Common mistakes

  • Using ?. so liberally that a genuinely broken/missing value is silently swallowed as undefined instead of surfacing a helpful error.

  • Using || for defaults when 0, "", or false are valid values you don't want replaced — ?? is usually the safer choice.

  • Forgetting that ?. only guards against null/undefined, not against other unexpected types.

Practice exercises

  1. Easy:

    Use optional chaining to safely read user.profile.bio when profile might be missing.

  2. Medium:

    Use ?? to provide a default page size of 10 when a pageSize variable might be 0, null, or undefined — and explain why || would behave differently.

  3. Hard:

    Rewrite a function that used several && checks to safely access nested data, using optional chaining and nullish coalescing instead.

Interview questions

What does `?.` do?

It safely accesses a property, only continuing if the value to its left isn't null or undefined, otherwise short-circuiting to undefined instead of throwing.

How is `??` different from `||`?

?? only falls back when the left side is null or undefined; || falls back for any falsy value, including 0, "", and false.

Can you call a function with optional chaining?

Yes — obj.method?.() calls method only if it exists, otherwise evaluates to undefined.