Skip to content
Theory · Objects · lesson 10 of 13

Optional chaining

Picture a chain of cards: from a user's form to a card with the address, and from it to the city. Some users have an address card and some do not. When there is no card, you cannot look for the "City" line on it.

In that case the program stops:

JavaScript
const user = { name: "Ann" };

console.log(user.address); // undefined
console.log(user.address.city); // ✗
TEXT
TypeError: Cannot read properties of undefined (reading 'city')

Let's see what happened:

  1. user.address gives undefined: there is no property address, but that is not an error yet.
  2. user.address.city reads .city from undefined. undefined has no properties, and reading .city is already an error.

The same happens with the value null. An if check before every dot would make the code long: if (user.address !== undefined) for every link.

The ?. operator

Optional chaining is the ?. operator in place of a dot. When the value left of ?. is null or undefined, the whole expression gives undefined, and there is no error. Otherwise ?. reads the property like an ordinary dot:

JavaScript
const ann = { name: "Ann" };
const bob = { name: "Bob", address: { city: "Oslo" } };

console.log(ann.address?.city); // undefined
console.log(bob.address?.city); // Oslo
console.log(ann.address?.city ?? "unknown"); // unknown

Let's go through it line by line:

  1. ann has no address: ann.address is undefined, and ?. stops the reading.
  2. bob has an address, and ?.city reads the city like an ordinary dot.
  3. The last line puts "unknown" in place of undefined.

In the filing cabinet, ?. is like a careful helper. It looks into the drawer, and if the card is not there, it answers "no data" instead of looking for a line on nothing.

Two more forms of the same notation:

  • a chain can check several links: order?.client?.address;
  • for a key from a variable, there is a form with brackets: user.address?.[field].

A fallback with ??

The ?? operator puts in a fallback value when the chain gave undefined. It has to be ?? here, not ||: with ||, an empty string or 0 in the property would also turn into the fallback.

Interviewers like to ask about the difference between ?? and ||. || replaces any falsy value, and ?? replaces only null and undefined.

Take a flat on the ground floor: const flat = { floor: 0 }. The expression flat?.floor ?? 1 gives 0, as the data says. The expression flat?.floor || 1 gives 1: the || operator took zero for a missing value, and the floor got lost.

Where the chain stops

When ?. meets undefined, the rest of the chain to its right is not evaluated: ann.address?.city.length also gives undefined, with no error.

Why is there no error on .length? ?. cuts off not one link but the whole chain to its right. Having found no card, the helper does not walk further along the chain; it returns the answer at once.

When to use ?.

Put ?. only where a value may be missing by the meaning of the data. When a property must be there, an ordinary dot reports the error honestly, while ?. hides it behind undefined.

Here the helper analogy stops working: ?. can only read. Assigning through ?. is not allowed: user?.name = "Bob" is a SyntaxError.

Common mistake

?. was put on the wrong link of the chain:

JavaScript
const user = { name: "Ann" };

console.log(user?.address.city); // ✗
TEXT
TypeError: Cannot read properties of undefined (reading 'city')

?. checks only the value left of it. Here that is user, which exists, so the reading goes on, and .city is read from undefined.

The sign belongs after the property that may be missing: user.address?.city. If the message is the same as without ?., the check is on the wrong link.

Key points

  • a?.b gives undefined when a is null or undefined, and otherwise reads b like a dot.
  • As soon as ?. meets null or undefined, the rest of the chain to its right is not evaluated.
  • ?? puts in a fallback only for null and undefined, leaving 0 and the empty string alone.
  • ?. goes right after the link that may be missing.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way