🌱BeginnerModern JavaScript
Optional Chaining & Nullish Coalescing
The ?. and ?? operators safely navigate nested properties and provide fallback values.
Overview
Two modern JavaScript operators transform how you handle potentially missing or null values.
**Optional chaining (`?.`)** lets you safely access nested object properties without throwing if an intermediate value is `null` or `undefined`. Instead of crashing with "Cannot read properties of undefined", it short-circuits and returns `undefined`. Works on property access (`a?.b`), method calls (`a?.method()`), and array access (`a?.[i]`).
**Nullish coalescing (`??`)** returns the right-hand side only when the left is `null` or `undefined` not for all falsy values. This is a key difference from `||`: `0 ?? "default"` returns `0` (because 0 is not null/undefined), while `0 || "default"` returns `"default"` (because 0 is falsy). Use `??` when 0 or `""` are valid values.
They compose beautifully: `user?.address?.city ?? "Unknown"`.
Key Points
- •`obj?.prop` returns `undefined` (not an error) if `obj` is null/undefined
- •`obj?.method()` calls the method only if obj is not null/undefined
- •`arr?.[index]` safe index access; `fn?.(args)` safe function call
- •`??` returns the right side only when left is `null` or `undefined`
- •`||` returns the right side for ANY falsy value (0, "", false, null, undefined, NaN)
- •`??=` (nullish assignment) assign only if the current value is null/undefined: `x ??= "default"`
- •`||=` assign only if current value is falsy; `&&=` assign only if current value is truthy
- •Chain them: `a?.b?.c?.d ?? "fallback"` returns "fallback" if any link is null/undefined
Examples
Optional chaining on nested objects
const user = {
name: "Alice",
address: {
city: "London",
postcode: "W1A 1AA"
}
};
const userNoAddress = { name: "Bob" };
// Without ?. crashes if address is undefined
// console.log(userNoAddress.address.city); // TypeError!
// With ?. safe navigation
console.log(user?.address?.city); // "London"
console.log(userNoAddress?.address?.city); // undefined (no crash)
// Method call
console.log(user?.address?.toUpperCase?.()); // undefined (no method)
console.log(user?.name?.toUpperCase()); // "ALICE"
// Array element
const data = { items: [10, 20, 30] };
console.log(data?.items?.[1]); // 20
console.log(data?.missing?.[0]); // undefinedNullish coalescing vs logical OR
// ?? vs || the key difference
const count = 0;
const name = "";
console.log(count || "no count"); // "no count" (0 is falsy!)
console.log(count ?? "no count"); // 0 (0 is not null/undefined)
console.log(name || "anonymous"); // "anonymous" ("" is falsy!)
console.log(name ?? "anonymous"); // "" ("" is not null/undefined)
// Safe defaults for potentially null API responses
const config = {
retries: 0, // valid setting
timeout: null, // explicitly not set
};
const retries = config.retries ?? 3; // 0 (correct!)
const timeout = config.timeout ?? 5000; // 5000 (correct!)
const missing = config.debug ?? false; // false (correct!)
console.log(retries, timeout, missing);Nullish assignment operators
// ??= assign only if null or undefined
let username = null;
username ??= "guest";
console.log(username); // "guest"
let score = 0;
score ??= 100; // 0 is not null/undefined
console.log(score); // 0 (unchanged)
// ||= assign only if falsy
let title = "";
title ||= "Untitled";
console.log(title); // "Untitled" ("" is falsy)
// &&= assign only if truthy
let admin = true;
admin &&= "super-admin";
console.log(admin); // "super-admin" (was truthy)
// Practical: initialise object property once
const cache = {};
cache.hits ??= 0;
cache.hits++;
console.log(cache.hits); // 1Common Mistakes
- Using `||` instead of `??` for defaults when 0 or `""` are valid values `0 || 5` gives 5, not 0
- Optional chaining doesn't protect against calling a method that exists but throws it only guards against null/undefined
- Over-chaining `?.` on everything hides bugs if a value should always be present, a crash is better than a silent undefined
Note
A good rule: use `??` for defaults (protecting against unset values), use `||` when you want to replace any falsy value. Use `?.` when a property is genuinely optional not just when you're unsure if data is valid.
Exercises
Write JavaScript code to solve each exercise. Run it and check your output.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4