Technology · JavaScript
IntermediateJavaScript Optional Chaining
Access nested properties safely with optional chaining and pair it with nullish coalescing for defaults.
TL;DR
- 01Access nested properties safely with the ?. operator.
- 02Provide fallback values for null using the ?? operator.
- 03Short-circuit chains the moment a value is nullish.
Optional Chaining Basics
- Use
?.to read a nested property without throwing when a parent is missing.const user = { profile: null }; console.log(user.profile?.email); // undefined, no error - Compare this to plain dot access, which throws a TypeError on a null parent.
console.log(user.profile.email); // TypeError: Cannot read properties of null - Chain multiple
?.together to guard against several possibly-missing levels.const data = {}; console.log(data.user?.address?.city); // undefined - Optional chaining works the same for deeply nested API response shapes.
const city = response?.data?.user?.address?.city; - Mix
?.with regular dot access once you're sure a value exists.console.log(user.profile?.settings.theme); // safe up to settings, then normal access
Optional Method and Array Access
- Use
?.()to call a method only if it actually exists on the object.const obj = {}; obj.greet?.(); // does nothing, no error - This is useful for optional callback props in component-style code.
function handleClick(onClick) { onClick?.(); // calls onClick only if it was provided } - Use
?.[index]to safely access array items or computed keys.const arr = null; console.log(arr?.[0]); // undefined - Combine bracket and dot chaining when working with dynamic data shapes.
console.log(data?.items?.[0]?.name); - Optional chaining on arrays prevents errors when an API returns null instead of an empty array.
const list = response?.results ?? []; list.forEach(item => console.log(item));
Nullish Coalescing for Defaults
- Use
??to supply a fallback only when the left side is null or undefined.const name = user.name ?? 'Anonymous'; - Unlike
||,??keeps falsy-but-valid values like 0 or an empty string.const count = 0; console.log(count ?? 10); // 0 console.log(count || 10); // 10, probably wrong here - Pair
?.and??together for safe access plus a sensible default in one line.const theme = user.settings?.theme ?? 'light'; - Use
??=to assign a default only if the variable is currently null or undefined.let config = {}; config.timeout ??= 3000; console.log(config.timeout); // 3000 - Avoid mixing
??directly with&&or||without parentheses, since JavaScript forbids it.// const x = a || b ?? c; // SyntaxError const x = (a || b) ?? c; // valid with explicit grouping
Short-Circuiting Behavior
- Evaluation stops the instant a
?.link finds null or undefined.function getEmail() { console.log('called'); return 'a@b.com'; } const user = null; user?.getEmail(); // "called" never logs, short-circuited - Function calls after a short-circuit point never execute, which avoids unwanted side effects.
obj?.save?.(logChange()); // logChange() still runs, save?.() does not, if obj is null - The whole chained expression resolves to
undefinedonce short-circuited, notnull.console.log(null?.a?.b); // undefined, even though we started with null - Optional chaining short-circuits independently at each
?., not the entire statement at once.const result = a?.b.c?.d; // only guards at the two ?. points, not the plain .c access - Combine short-circuiting with
??to build defensive code that never throws on missing data.function getCityOrDefault(user) { return user?.address?.city ?? 'Unknown city'; }
Tips
- 01Combine ?. with ?? to safely read a deep property and supply a sensible default in a single readable expression.
- 02Use optional chaining on method calls with ?.() when a function might not exist on the object yet.
- 03Reach for nullish coalescing instead of the logical OR operator whenever zero or an empty string are valid values.
Warnings
- 01Optional chaining only guards against null and undefined, not other falsy values like 0 or an empty string.
- 02Overusing ?. everywhere can hide real bugs by silently swallowing errors that should surface during development.
- 03The || operator treats 0, empty strings, and false as missing, which often produces wrong defaults compared to ??.
FAQ
- Optional chaining checks if the value to its left is null or undefined before continuing the property access. If it is nullish, the entire expression short-circuits and returns undefined instead of throwing a TypeError. This avoids long chains of manual null checks.
- The || operator falls back to its right-hand value for any falsy left-hand value, including 0, '', and false. The ?? operator only falls back when the left-hand value is null or undefined. Use ?? when zero or an empty string should be treated as valid data.
- Yes. Use ?.() to call a function only if it exists, like obj.method?.(). Use ?.[index] for array or computed property access, like arr?.[0]. Both forms short-circuit to undefined if the preceding value is nullish.
- Yes, this is called short-circuiting. As soon as any link in the chain is null or undefined, evaluation stops immediately. The whole expression returns undefined, and any function calls further down the chain never execute.
- No, you cannot use ?. on the left side of an assignment, like obj?.prop = value; that throws a SyntaxError. Optional chaining is read-only and meant for safely accessing values, not for conditionally writing them.