Overview: the double question mark in JavaScript

The double question mark (??) in JavaScript, also known as the nullish coalescing operator, is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, otherwise it returns the left-hand side. This operator provides a cleaner syntax for selecting the first "defined" value from a list. In this guide, we’ll cover the operator and its use cases.

What is the ?? operator?

JS developers often encounter scenarios where a default value is required in case a given value is null or undefined. Before ES2020, which introduced the ?? operator, this was commonly handled by logical OR (||). However, the OR operator falls short in certain cases because it returns the right-hand side operand for any falsy value (0, '', false, null, undefined, NaN), which can lead to unintended consequences like incorrectly evaluating a valid falsy input as a reason to use a default value.

How does the double question mark work?

The ?? operator works by evaluating the left-hand side expression first. If the result is not null or undefined, it is returned. Otherwise, the right-hand side is evaluated and returned. Here’s the basic syntax:

let result = value1 ?? value2;

If value1 is null or undefined, result will be value2. Otherwise, result will be value1.

Use cases for ??

The ?? operator is particularly useful when you have a chain of potential values and you want to pick the first one that isn’t null or undefined. It’s perfect for setting default values for variables that may not be initialized.

let options = userOptions ?? defaultOptions;

In this code snippet, options will be assigned to userOptions if it’s not null or undefined; otherwise, defaultOptions will be used.

Differences between ?? and ||

It’s important to distinguish ?? from the || operator. Here's an example highlighting the difference:

let quantity = 0; let defaultQuantity = 10; let orderQuantity = quantity || defaultQuantity; // This will be 10 let correctOrderQuantity = quantity ?? defaultQuantity; // This will be 0

With ||, orderQuantity gets the value of 10 because 0 is a falsy value. With ??, correctOrderQuantity preserves the value 0 since it’s not null or undefined.

Combining ?? with other operators

When combining ?? with other JavaScript operators, be mindful of precedence. ?? has lower precedence than most other operators, but it’s higher than = and ?. You often need parentheses when combining it with certain operators to ensure the correct order of evaluation.

For example:

let foo = null; let bar = 0; let baz = 'default'; let result = foo ?? (bar || baz); // This will evaluate to 0

Without the parentheses, it would throw an error because ?? cannot be directly mixed with || without explicit parentheses.

Potential pitfalls

  • You cannot mix the ?? operator with && or || without explicit parentheses due to JavaScript’s parsing rules.
  • If you transpile your code to be compatible with older JavaScript engines, ensure your transpiler supports the ?? operator.
  • Remember that only null and undefined are considered "nullish". Other falsy values like 0, '', or NaN are not.

Browser and environment compatibility

As of ES2020, the ?? operator is part of the JavaScript specification, which means it's widely supported in modern browsers and JavaScript runtimes like Node.js. However, for older environments, you may still need to use a transpiler like Babel.

Detailed usage and examples

Beyond simple value assignment, ?? can be incredibly useful in a variety of contexts:

Function arguments: Providing defaults for function parameters that haven't been passed or are null:

function greet(name) { name = name ?? 'Guest'; console.log(`Hello, ${name}!`); }

Ternary operations: Using ?? within a ternary operation to provide a default for a potentially nullish condition:

const response = fetchData(); const data = response ? response.data : 'No data'; const message = data ?? 'Default message';

Complex expressions: Managing state in applications, especially when dealing with store values that may not be initialized:

const state = { user: { name: null, age: 25, }, }; const userName = state.user.name ?? 'Anonymous'; const userAge = state.user.age ?? 18;

Interaction with Optional Chaining

The optional chaining operator ?. can be used in conjunction with ?? to provide a default value after checking for null or undefined properties in a chain:

const user = { profile: { name: null, }, }; const userName = user.profile.name?.toUpperCase() ?? 'No name provided';

In this example, if user.profile.name is null, then 'No name provided' will be used.

Nesting ??

It’s also possible to nest ?? for multiple layers of null checks:

const config = { header: null, title: null, fallback: 'Default Title', }; const pageTitle = config.header ?? config.title ?? config.fallback;

This sets pageTitle to config.header, config.title, or config.fallback, whichever is the first value that isn’t null or undefined.

Polyfills and Transpilation

To ensure compatibility with older browsers, you can use a polyfill for ??. Alternatively, a transpiler like Babel with the appropriate plugins can convert ?? into ES5-compliant code:

// Babel can transpile `??` into something like this: var result = value1 !== null && value1 !== void 0 ? value1 : value2;

Conclusion

The double question mark is a significant addition to JavaScript. It provides a more robust way to set default values and can simplify code by avoiding unintended falsy evaluations. Understanding how and when to use it will enhance your coding style and prevent common bugs associated with null and undefined checks.

Invite only

The next generation of charts.

Coming soon.

The next generation of charts. Coming soon.

The next generation of charts. Coming soon.

Fast. Opinionated. Collaborative. Local-first. Keyboard centric. Crafted to the last pixel. We've got 50 slots for Alpha access.