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
andundefined
are considered "nullish". Other falsy values like0
,''
, orNaN
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
Fast. Opinionated. Collaborative. Local-first. Keyboard centric. Crafted to the last pixel. We've got 50 slots for Alpha access.
How to Remove Characters from a String in JavaScript
Jeremy Sarchet
How to Sort Strings in JavaScript
Max Musing
How to Remove Spaces from a String in JavaScript
Jeremy Sarchet
Detecting Prime Numbers in JavaScript
Robert Cooper
How to Parse Boolean Values in JavaScript
Max Musing
How to Remove a Substring from a String in JavaScript
Robert Cooper