JavaScript Series #25: The Nullish Coalescing Operator
In the world of JavaScript, providing default values is a common task. Whether you're dealing with potentially missing API data, optional user configurations, or just ensuring a variable always has a fallback, you've likely used the logical OR operator (||) for this purpose. While incredibly useful, the || operator has a specific behavior that can sometimes lead to unexpected results. Enter the Nullish Coalescing Operator (??), a newer addition to JavaScript (ES2020) designed to offer a more precise way to handle default values.
What is the Nullish Coalescing Operator (??)?
The nullish coalescing operator (??) is a logical operator that returns its right-hand operand when its left-hand operand is null or undefined. Otherwise, it returns its left-hand operand.
Think of it as a stricter version of the logical OR operator (||) for default assignments. It only "coalesces" (i.e., falls back to the default value) if the value on its left is truly missing or undefined, not just "falsy."
How ?? Differs from || (Logical OR)
The key distinction lies in what each operator considers "empty" or "false-like":
- The logical OR operator (
||) considers any falsy value as a trigger to use the right-hand operand. Falsy values in JavaScript include:false,0,''(empty string),null,undefined, andNaN. - The nullish coalescing operator (
??) only considersnullandundefinedas triggers to use the right-hand operand. It treats other falsy values (false,0,'',NaN) as valid, "truthy" values that should be returned.
Let's look at some examples to illustrate this critical difference:
Example 1: Numeric Values (0)
let count = 0;
let defaultCount = 10;
// Using logical OR (||)
let resultOR = count || defaultCount;
console.log(`Result with ||: ${resultOR}`); // Output: Result with ||: 10
// Explanation: 0 is falsy, so || returns defaultCount.
// Using nullish coalescing (??)
let resultNCO = count ?? defaultCount;
console.log(`Result with ??: ${resultNCO}`); // Output: Result with ??: 0
// Explanation: 0 is not null or undefined, so ?? returns count.
In this case, if 0 is a valid and desired value, || fails because it treats 0 as falsy, whereas ?? correctly preserves 0.
Example 2: Empty Strings ('')
let username = '';
let defaultUsername = 'Guest';
// Using logical OR (||)
let resultOR = username || defaultUsername;
console.log(`Result with ||: ${resultOR}`); // Output: Result with ||: Guest
// Explanation: '' (empty string) is falsy, so || returns defaultUsername.
// Using nullish coalescing (??)
let resultNCO = username ?? defaultUsername;
console.log(`Result with ??: ${resultNCO}`); // Output: Result with ??:
// Explanation: '' is not null or undefined, so ?? returns username.
Similarly, an empty string '' might be a perfectly valid input or state. || would overwrite it, while ?? respects it.
Example 3: Boolean Values (false)
let isActive = false;
let defaultActiveStatus = true;
// Using logical OR (||)
let resultOR = isActive || defaultActiveStatus;
console.log(`Result with ||: ${resultOR}`); // Output: Result with ||: true
// Explanation: false is falsy, so || returns defaultActiveStatus.
// Using nullish coalescing (??)
let resultNCO = isActive ?? defaultActiveStatus;
console.log(`Result with ??: ${resultNCO}`); // Output: Result with ??: false
// Explanation: false is not null or undefined, so ?? returns isActive.
If false is a meaningful state (e.g., a user explicitly disabled a setting), ?? allows you to preserve it.
Example 4: Nullish Values (null or undefined)
let config = null;
let defaultPort = 8080;
// Using logical OR (||)
let resultOR = config?.port || defaultPort; // Using optional chaining for safety
console.log(`Result with ||: ${resultOR}`); // Output: Result with ||: 8080
// Using nullish coalescing (??)
let resultNCO = config?.port ?? defaultPort; // Using optional chaining for safety
console.log(`Result with ??: ${resultNCO}`); // Output: Result with ??: 8080
In cases where the left-hand operand is genuinely null or undefined, both operators yield the same result.
Use Cases and Benefits
The nullish coalescing operator shines in scenarios where you need to distinguish between actual missing values and other falsy values:
- Configuration Defaults: When settings might be explicitly set to
0,false, or'', but should fall back to a default if truly absent.const userSettings = { theme: 'dark', notifications: false, fontSize: null // Or undefined from an API }; const theme = userSettings.theme ?? 'light'; // 'dark' const notifications = userSettings.notifications ?? true; // false const fontSize = userSettings.fontSize ?? 16; // 16 const animationSpeed = userSettings.animationSpeed ?? 500; // 500 (since animationSpeed is undefined) console.log({ theme, notifications, fontSize, animationSpeed }); // { theme: 'dark', notifications: false, fontSize: 16, animationSpeed: 500 } - Handling API Responses: When an API might return
0for a quantity orfalsefor a boolean flag, but you want a default if the property itself is missing or explicitlynull. - Refactoring Legacy Code: It can replace verbose conditional checks like
if (value === null || value === undefined) { ... }with a more concise expression.
Operator Precedence
The nullish coalescing operator has a lower precedence than most other operators, like arithmetic, comparison, and bitwise operators, but higher than assignment operators. It's similar in precedence to || and &&.
Important: It is not possible to combine the nullish coalescing operator (??) directly with the logical AND (&&) or OR (||) operators without surrounding them with parentheses. This is a deliberate syntactic restriction to avoid common programming mistakes, as their interactions can be confusing.
// This will throw a SyntaxError:
// let result = 0 ?? true || false;
// You must use parentheses:
let result = (0 ?? true) || false; // Evaluates to 0 || false, which is false
console.log(result); // Output: false
let anotherResult = true && (undefined ?? 'default'); // Evaluates to true && 'default', which is 'default'
console.log(anotherResult); // Output: default
Browser Support
The Nullish Coalescing Operator is part of ECMAScript 2020 (ES2020). This means it is supported in modern browsers and Node.js versions. If you need to support older environments, you might need to use a transpiler like Babel to convert your code to an older JavaScript version.
Conclusion
The Nullish Coalescing Operator (??) is a valuable addition to JavaScript, providing a more precise and robust way to handle default values. By distinguishing between null/undefined and other falsy values like 0, '', and false, it allows developers to write cleaner, more predictable, and less error-prone code when assigning fallbacks. Incorporating ?? into your codebase will lead to more explicit intent and fewer subtle bugs related to truthiness in JavaScript.