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/undefinedOptional 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 asundefinedinstead of surfacing a helpful error.Using
||for defaults when0,"", orfalseare valid values you don't want replaced —??is usually the safer choice.Forgetting that
?.only guards againstnull/undefined, not against other unexpected types.
Practice exercises
- Easy:
Use optional chaining to safely read
user.profile.biowhenprofilemight be missing. - Medium:
Use
??to provide a default page size of 10 when apageSizevariable might be0,null, orundefined— and explain why||would behave differently. - 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.