JavaScript Optional Chaining

Read Something That Might Not Be There

JavaScript Optional Chaining

The `?.` operator safely reads properties on values that might be `null` or `undefined` — no crash, no manual checks.

4 min read Level 2/5 #optional-chaining#null#undefined
What you'll learn
  • Use `?.` to safely read deep properties
  • Combine with `??` for clean defaults
  • Use `?.()` for optional method calls

When you try to read a property of null or undefined, JavaScript throws a TypeError. The optional chaining operator ?. makes the read return undefined instead.

?. avoids the crash script.js
const user = null;

// console.log(user.name);    // TypeError: Cannot read properties of null

console.log(user?.name);      // undefined  ← safe, no crash
▶ Preview: console

Chaining Through Nested Properties

The real power: chains. If anything along the way is null or undefined, the whole expression evaluates to undefined.

Deep optional chain script.js
const user = {
  name: "Ada",
  address: {
    city: "London",
  },
};

console.log(user?.address?.city);       // "London"
console.log(user?.address?.zipCode);    // undefined  (no zipCode property)
console.log(user?.profile?.bio);        // undefined  (no profile)
console.log(user?.profile?.bio?.length); // undefined (chain stops at profile)
▶ Preview: console

Compare with the old way:

// Without ?.:
const city = user && user.address && user.address.city;

// With ?.:
const city = user?.address?.city;

Combine With ?? for Defaults

?. returns undefined when something’s missing. Pair with ?? for a default value.

?. with ?? script.js
const user = { name: "Ada" };

const city = user?.address?.city ?? "unknown";
console.log(city);  // "unknown"
▶ Preview: console

Optional Method Calls With ?.()

?.() calls a function only if it exists. If it’s null or undefined, the call is skipped (returns undefined).

Optional call script.js
const obj = {
  greet() { return "hello!"; },
};

console.log(obj.greet?.());        // "hello!"
console.log(obj.missingMethod?.()); // undefined  ← no crash
▶ Preview: console

This is great for optional callbacks:

function doWork(onProgress) {
  // call only if a callback was passed
  onProgress?.(50);
}

Optional Array Access With ?.[]

Same idea for [index] lookups when the array itself might be missing.

?.[] for arrays script.js
function firstUserName(users) {
  return users?.[0]?.name ?? "no users";
}

console.log(firstUserName([{ name: "Ada" }])); // "Ada"
console.log(firstUserName(null));               // "no users"
console.log(firstUserName([]));                 // "no users"
▶ Preview: console

What ?. Does NOT Do

  • It doesn’t silently swallow all errors — only the null/ undefined case. Calling a non-function still throws.
  • It doesn’t catch typos. user?.adress returns undefined, the same as a missing property.

Up Next

You’ve covered all the major decision-making tools. Time for loops.

JavaScript for Loops →