Q30 of 40 · JavaScript
How do optional chaining (`?.`) and nullish coalescing (`??`) work?
Short answer
Short answer: Optional chaining `?.` short-circuits to `undefined` if the left side is `null` or `undefined`, preventing TypeError on deep property access. Nullish coalescing `??` returns the right-hand side only when the left is `null` or `undefined` — unlike `||`, it preserves falsy values like `0` or `''`.
Detail
These two operators work together to safely access and default nested data without verbose null checks.
Optional chaining (?.):
a?.breturnsundefinedifais null/undefined, otherwise evaluatesa.ba?.[key]for dynamic property accessfn?.(args)for optional function calls- Chains short-circuit:
a?.b?.cstops at the first null/undefined
Nullish coalescing (??):
a ?? breturnsbonly whenaisnullorundefined- Preserves falsy values:
0 ?? 5→0;'' ?? 'default'→''' - Contrast with
||:0 || 5→5(0 is falsy, so the right side is used — often a bug)
Combining: user?.profile?.score ?? 0 safely navigates to score and defaults to 0 if any segment is nullish.
In test automation: These operators are used throughout Playwright assertions and API response processing — safely accessing response?.data?.items?.[0] without crashing on empty responses.
// EXAMPLE
const user = { profile: { score: 0 } };
const noUser = null;
// Optional chaining
console.log(user?.profile?.score); // 0
console.log(noUser?.profile?.score); // undefined (no TypeError)
console.log(user?.address?.city); // undefined
// Nullish coalescing — preserves 0 and ''
console.log(user?.profile?.score ?? 100); // 0 (not 100!)
console.log(0 ?? 100); // 0
console.log(0 || 100); // 100 (often a bug)
console.log('' ?? 'default'); // ''
console.log('' || 'default'); // 'default'
// API response in tests
const items = response?.data?.items ?? [];
const first = items[0]?.name ?? "unknown";