JavaScript Optional Chaining
Access nested properties safely with optional chaining and pair it with nullish coalescing for defaults.
TL;DR
- 01Access nested properties safely using the
?.operator. - 02Provide fallback values for missing properties using the
??operator. - 03Short-circuit evaluation chains immediately when any intermediate value is nullish.
Tips
- 01Combine the
?.and??operators to read nested properties and supply fallback values in one statement. - 02Utilize optional chaining with
?.()when invoking callback methods that might not exist on target objects.
Warnings
- 01Remember that optional chaining only guards against
nullandundefinedrather than other falsy values. - 02Avoid overusing the
?.operator because it can hide actual bugs by silently swallowing unexpected errors.
Optional Chaining Basics
?.Accesses nested properties safely without throwing errors if the parent object is nullish.
const user = { profile: null };
const email = user.profile?.email; // undefinedPlain dot accessThrows a TypeError if you attempt to read properties of a missing parent.
const user = { profile: null };
// Throws: Cannot read properties of null
const email = user.profile.email;Multi-level chainingChains multiple optional checks together to guard against several missing layers.
const data = {};
const city = data.user?.address?.city; // undefinedMixed chainingCombines optional chaining with standard dot access once existence is verified.
const user = {
profile: { settings: { theme: "dark" } }
};
const theme = user.profile?.settings.theme; // safeMethod and Array Access
?.()Invokes an object method conditionally only if it is defined and executable.
const obj = {};
obj.greet?.(); // does nothing, no errorOptional callbacksInvokes optional callback parameters in a function safely to prevent errors.
function handleClick(onClick) {
onClick?.(); // calls only if provided
}?.[index]Accesses array elements or computed keys safely when the parent list is nullish.
const arr = null;
const item = arr?.[0]; // undefinedDynamic objectsCombines optional brackets and dot identifiers when walking variable data shapes.
const res = data?.items?.[0]?.name;Nullish Coalescing
??Returns the right-hand value only when the left-hand expression is nullish.
const name = user.name ?? "Anonymous";?? versus ||Preserves falsy values like zero or empty strings, unlike standard logical OR.
const count = 0;
console.log(count ?? 10); // 0
console.log(count || 10); // 10Safeguard chainCombines optional chaining and nullish fallback to supply safe defaults.
const theme = user.settings?.theme ?? "light";??=Assigns a default value to a variable only if it is currently nullish.
let config = {};
config.timeout ??= 3000;
console.log(config.timeout); // 3000Short-Circuiting
Evaluation haltStops expression evaluation immediately when a nullish value is encountered.
let called = false;
const getEmail = () => { called = true; };
const user = null;
user?.getEmail();
console.log(called); // falseExpressions valueResolves the entire chained expression to undefined when short-circuited.
const val = null?.a?.b;
console.log(val); // undefinedIndependent checksShort-circuits exclusively at optional chain points rather than plain dots.
const obj = { a: null };
// Throws TypeError: Cannot read property c of null
const val = obj.a?.b.c;In Practice
Extracts nested settings from an optional server configuration object, applying defaults and executing callback functions safely.
- 01Isolate the network configuration block using optional property chaining.
- 02Resolve the server host name and port value, applying default fallbacks.
- 03Retrieve the application debug flag using nullish coalescing to preserve false values.
- 04Capture the initialization callback function using optional method verification.
- 05Assemble the final config object, invoking the callback conditionally.
function getAppConfig(serverConfig) {
const net = serverConfig?.network;
const host = net?.host ?? "localhost";
const port = net?.port ?? 8080;
const debug = serverConfig?.debug ?? false;
const onReady = serverConfig?.callbacks?.onReady;
return {
connection: `${host}:${port}`,
debug,
initialize: () => onReady?.()
};
}FAQ
Optional chaining verifies if the value to its left is null or undefined before accessing properties. If it is nullish, the expression short-circuits and evaluates to undefined. This prevents throwing TypeError errors.
The || operator falls back for any falsy value, including 0, empty strings, and false. The ?? operator only falls back for null or undefined. Use ?? when other falsy values are valid.
Yes, use ?.() to call a function only if it exists. Use ?.[index] to safely query array indexes or dynamic keys. Both forms resolve to undefined if the preceding value is nullish.
Yes, this behavior is known as short-circuiting. As soon as any link in the chain finds a nullish value, execution stops. The expression immediately returns undefined without executing subsequent operations.
No, you cannot use optional chaining on the left side of assignments. For example, obj?.prop = value throws a SyntaxError. The operator is strictly read-only and cannot write data.