How do optional chaining (?.) and nullish coalescing (??) work?
?. safely accesses nested properties without throwing if an intermediate value is null or undefined. ?? provides a fallback only for null/undefined.
JavaScript
Overview
Optional chaining (`?.`) and nullish coalescing (`??`) were introduced in ES2020 to eliminate verbose null checks when working with deeply nested data. Together they are the modern replacement for long `&&` chains and `||` fallback patterns.
Key Points
- •`obj?.prop` returns `undefined` instead of throwing if `obj` is `null` or `undefined`.
- •`arr?.[index]` and `fn?.()` - optional chaining also works on bracket access and function calls.
- •`a ?? b` returns `b` only when `a` is `null` or `undefined` (unlike `||` which also catches `0`, `""`, `false`).
- •They compose: `user?.address?.city ?? "Unknown"` safely navigates and falls back.
- •Short-circuits: if the left side is `null`/`undefined`, the right side is not evaluated.
Examples
Optional chaining for nested object access
javascriptconst user = {
profile: {
address: { city: 'Austin' }
}
};
// Without optional chaining (verbose)
const city = user && user.profile && user.profile.address && user.profile.address.city;
// With optional chaining
const city = user?.profile?.address?.city; // 'Austin'
// If address is missing:
const zip = user?.profile?.address?.zip; // undefined (no throw)Optional method calls
javascript// Only call if the method exists
const result = obj.transform?.();
// Works with array access too
const first = arr?.[0];
// Call a callback only if provided
function process(data, callback) {
const processed = transform(data);
callback?.(processed); // no-op if callback is undefined
}Nullish coalescing for fallback values
javascriptconst config = { timeout: 0, retries: null };
// || is wrong here: 0 is falsy, falls back to 3000 incorrectly
const timeout = config.timeout || 3000; // 3000 (BUG!)
// ?? only falls back for null/undefined
const timeout = config.timeout ?? 3000; // 0 (correct)
const retries = config.retries ?? 3; // 3 (retries was null)Combining ?. and ?? for safe navigation with fallback
javascriptconst displayName = user?.profile?.displayName ?? user?.name ?? 'Anonymous';
const streetLine = order?.shippingAddress?.street ?? 'No address on file';Pro Tip
Do not over-use `?.` - if a value should always exist, optional chaining hides bugs by silently returning `undefined`. Only use it where `null`/`undefined` is genuinely expected (optional fields, API responses that might omit data).