Optional Chaining and Coalescing

Introduction: The Problem of Missing Data

In our previous lessons, we learned how to structure data using objects and arrays, and how to unpack that data efficiently using destructuring. However, in real-world programming, data is rarely perfect. You will often receive information from a database or an external API where certain pieces of information are missing.

If you try to access a property on a value that is null or undefined while moving through a nested object, JavaScript will throw an error and stop your entire program from running. This is one of the most common causes of crashes in web applications.

To help us write safer code, modern JavaScript introduced two powerful tools: optional chaining (?.) and nullish coalescing (??). These operators allow us to navigate through uncertain data structures without the fear of breaking our application.

Optional Chaining Basics

The optional chaining operator, written as ?., allows you to read the value of a property located deep within a chain of connected objects without needing to check if each reference in the chain is valid. Normally, if you try to access a property on something that is null or undefined, JavaScript stops immediately with a TypeError.

When you use the ?. operator, JavaScript performs a quick check. If the value before the ?. is null or undefined, the expression "short-circuits" and returns undefined instead of crashing. This makes your code much cleaner because you no longer need to write long strings of if statements just to see if a nested object exists before you try to use it.

Chaining Through Deeply Nested Structures

Providing Fallback Values With Nullish Coalescing

Nullish Coalescing vs Logical OR

It is important to understand why we use ?? instead of the older logical OR operator (||). In JavaScript, the || operator returns the right-side value if the left side is "falsy." Falsy values include not just null and undefined, but also the number 0, an empty string "", and the boolean false. This can cause bugs if 0 or "" are actually valid pieces of data you want to keep.

"use strict";

const config = { retries: 0, label: "" };

console.log("retries (||):", config.retries || 3);
console.log("retries (??):", config.retries ?? 3);
console.log("label   (||):", config.label   || "n/a");
console.log("label   (??):", config.label   ?? "n/a");

Output:

retries (||): 3
retries (??): 0
label   (||): n/a
label   (??): 

In this configuration example, using || for retries is a mistake. Since 0 is a falsy value, the code falls back to 3, even though the user specifically wanted 0 retries.

The ?? operator is smarter because it only triggers a fallback if the value is strictly null or undefined. Similarly, for the label, the ?? operator respects the empty string, whereas || ignores it and uses the fallback text.

Optional Function Calls and Index Access

Optional chaining is not limited to object properties. You can also use it for calling functions that might not exist or accessing items in an array that might be empty. This is done using the ?.() syntax for functions and ?.[] for array indexes or dynamic property names.

"use strict";

const users = [
  { name: "Ada" }
];

const maybeFn = undefined;

console.log("call:",  maybeFn?.());
console.log("index:", users?.[99]?.name);

Output:

call: undefined
index: undefined

The first example shows an attempt to call maybeFn. Because maybeFn is undefined, the code simply returns undefined instead of throwing an error stating that maybeFn is not a function.

The second example looks for the 100th element in the users array. Since that index does not exist, it safely returns undefined for the name property. This syntax is very helpful when you are dealing with optional callbacks or large, unpredictable lists of data.

Summary and Next Steps

In this lesson, we covered how to defend your code against missing data using ?. and ??. You learned that optional chaining allows you to explore deeply nested objects without causing crashes when a property is missing. You also learned that the nullish coalescing operator provides a safe way to set default values without accidentally overwriting valid data like 0 or empty strings.

These operators are essential tools for a modern JavaScript developer. They help you write code that is shorter, easier to read, and much more resilient to errors. Now that you have seen how to handle uncertain data, it is time to practice these techniques in the CodeSignal IDE. Move on to the exercises to start building your own crash-resistant code.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal