const city = user?.address?.city; // undefined instead of throwing, if user or address is null/undefined
const label = value ?? "default"; // "default" only if value is null or undefined — 0 and "" are kept as-is
?. short-circuits the entire chain the moment it hits null/undefined — it doesn't just guard the one property access it's written on:
user?.address.city; // if user is null, stops immediately and returns undefined —
// never even attempts to read .city, so it can't throw on address being undefined either
Optional chaining also works for calling a method that might not exist, and for array/bracket access:
obj.someMethod?.(); // calls someMethod only if it exists, otherwise evaluates to undefined
arr?.[0]; // safe access to the first element, even if arr itself is null/undefined
?? is deliberately different from ||: value || "default" would incorrectly replace 0, "", or false with "default", since those are falsy but not actually "missing." ?? only falls back when the left side is specifically null or undefined:
const count = 0;
console.log(count || 10); // 10 — WRONG if 0 is a legitimate value, not "missing"
console.log(count ?? 10); // 0 — correct, 0 is kept because it isn't null/undefined