JavaScript Optional Chaining: Complete Guide

Optional chaining (?.) safely accesses nested properties without crashing. Learn how it works on objects, arrays, and function calls.

5 min read

Optional chaining (?.) lets you safely access deeply nested properties without crashing when something in the middle is null or undefined. Instead of throwing a type error, it short-circuits and returns undefined.

javascriptjavascript
const user = null;
 
// Without optional chaining: crashes
// console.log(user.address.city); // TypeError: Cannot read properties of null
 
// With optional chaining: safe, returns undefined
console.log(user?.address?.city); // undefined

This is the modern replacement for long chains of AND checks that were common before ES2020.

The Problem Optional Chaining Solves

Before optional chaining, accessing a nested property safely required checking every level:

javascriptjavascript
// Old way: verbose and repetitive
const city = user && user.address && user.address.city;
 
// New way: same safety, cleaner syntax
const city = user?.address?.city;

With the AND version, if any part of the chain is null or undefined, the expression short-circuits to undefined. Optional chaining does the same thing with less code.

Optional Chaining Variants

The ?. operator works in three places:

javascriptjavascript
// 1. Property access
user?.profile?.name
 
// 2. Method calls
user?.getDisplayName?.()
 
// 3. Array access / dynamic keys
users?.[0]
item?.[dynamicKey]

Property access

The most common use: accessing nested object properties without checking each level, which matters most when data comes from an API and some fields might be missing:

javascriptjavascript
const response = {
  data: {
    user: null
  }
};
 
console.log(response?.data?.user?.name); // undefined (safe, user is null)
console.log(response?.data?.user?.name ?? "Anonymous"); // "Anonymous" (with fallback)

Each ?. checks the value to its left. If it is null or undefined, the expression returns undefined and the rest of the chain is skipped.

Method calls

Call a method only if it exists:

javascriptjavascript
const obj = {
  greet: () => "Hello!"
};
 
console.log(obj.greet?.());     // "Hello!" (method exists, called normally)
console.log(obj.farewell?.());  // undefined (method does not exist, no error)

Without optional chaining, calling a method that does not exist would throw a type error and stop the script. With the optional call syntax, the call is simply skipped instead, and execution continues normally to whatever comes next.

Array access and dynamic keys

javascriptjavascript
const users = null;
 
console.log(users?.[0]);          // undefined (users is null)
console.log(users?.[0]?.name);    // undefined (chain stops at users)
 
const key = "address";
const data = { address: "123 Main St" };
console.log(data?.[key]);         // "123 Main St"

How Short-Circuiting Works

Optional chaining short-circuit flow

The chain evaluates left to right. The first null or undefined stops the entire expression and returns undefined. No further property accesses are attempted, which is what prevents the error.

This short-circuit behavior also means any side effects on the right side of ?. will not run if the left side is nullish:

javascriptjavascript
const obj = null;
obj?.computeExpensiveValue(); // computeExpensiveValue is never called

Practical Use Cases

Working with API responses

APIs often return partial data, and a field you expect to exist might be missing or null depending on server state. Optional chaining handles this gracefully:

javascriptjavascript
async function fetchUserName(userId) {
  const response = await fetch(`/api/users/${userId}`);
  const data = await response.json();
 
  return data?.user?.profile?.displayName ?? "Unknown User";
}

If the API returns a null user or a profile with no display name, the function returns "Unknown User" instead of crashing.

DOM element access

When an element might not exist on the page:

javascriptjavascript
const modal = document.querySelector(".modal");
modal?.classList.add("visible");

If the element is not in the DOM, the selector returns null, and optional chaining safely skips the class-list update instead of throwing an error and stopping the rest of the script.

Event handler access

javascriptjavascript
function handleEvent(event) {
  event?.preventDefault?.();
  // process event...
}

If event is null or if preventDefault is missing (unlikely in standard events, but common in custom event systems), the call is safely skipped.

What Optional Chaining Does Not Do

Optional chaining only protects against null and undefined. It does not protect against other errors:

javascriptjavascript
const user = { address: "123 Main St" };
 
console.log(user?.address?.city); // undefined (no city property, but no error)
console.log(user?.address?.toUpperCase()); // "123 MAIN ST" (address is a string, method exists)

If a property exists but is 0, an empty string, or false, optional chaining does not stop. It only stops on null and undefined.

To provide fallback values when the result is undefined, pair ?. with the nullish coalescing operator:

javascriptjavascript
const city = user?.address?.city ?? "No city provided";

Optional Chaining vs the && Pattern

?. (optional chaining)&& (logical AND)
Stops onnull, undefinedAny falsy value
Result when stoppedundefinedThe falsy value itself
ReadabilityClean, obvious intentVerbose, mechanical
Method callsobj.method?.()No direct equivalent

The AND pattern also stops on 0, an empty string, and false, which can hide real values. Optional chaining is more precise. For more on how AND short-circuiting works, see the logical short-circuiting guide.

Rune AI

Rune AI

Key Insights

  • ?. returns undefined if the left side is null or undefined, instead of throwing.
  • Use ?. for properties (user?.address?.city), methods (obj?.method?.()), and arrays (arr?.[0]).
  • ?. short-circuits: once it hits null/undefined, the rest of the chain is skipped.
  • ?. does not protect against non-null values that are missing a property.
  • Optional chaining is read-only. You cannot assign through ?..
  • Combine ?. with ?? to provide a fallback value when the chain returns undefined.
RunePowered by Rune AI

Frequently Asked Questions

What happens if I use ?. on a value that is not null or undefined?

?. works like regular . access when the value before it exists. user?.name is the same as user.name when user is an object. The check only matters when the left side is null or undefined.

Can I use optional chaining on the left side of an assignment?

No. You cannot write user?.name = 'Alice'. Optional chaining is only for reading values, not writing them. It would be unclear whether to skip the assignment or throw an error.

Does optional chaining work in all browsers?

Yes. Optional chaining was introduced in ES2020 and is supported in all modern browsers (Chrome 80+, Firefox 74+, Safari 13.1+, Edge 80+). It does not work in Internet Explorer.

Conclusion

Optional chaining (?.) is the safe way to access nested properties, array items, and function calls when something in the chain might be null or undefined. It short-circuits to undefined instead of throwing an error. Use it when working with API responses, user data, or any deeply nested structure where intermediate values are optional. It replaces long chains of && checks with a single ?. that is easier to read and write.