Nullish Coalescing vs Logical OR in JavaScript: When to Use ?? vs ||
JavaScript developers often need to provide default values when dealing with potentially missing data. Two operators serve this purpose: the nullish coalescing operator (??) and the logical OR operator (||). While they appear similar, they behave differently in crucial ways that can significantly impact your code.
The Fundamental Difference
- Logical OR (
||) returns the right-hand value if the left-hand value is falsy - Nullish Coalescing (
??) returns the right-hand value only if the left-hand value is nullish (nullorundefined)
TIP
JavaScript falsy values include: false, 0, -0, 0n, "", null, undefined, and NaN
Behavior Comparison
// Values that behave differently
console.log(0 || "default"); // "default"
console.log(0 ?? "default"); // 0
console.log("" || "default"); // "default"
console.log("" ?? "default"); // ""
console.log(false || "default"); // "default"
console.log(false ?? "default"); // false
// Values that behave the same
console.log(null || "default"); // "default"
console.log(null ?? "default"); // "default"
console.log(undefined || "default"); // "default"
console.log(undefined ?? "default"); // "default"Practical Examples
Form Handling
Consider a form where an empty string is a valid value:
// Problem with || when empty string is valid
const phoneInput = "";
const phone1 = phoneInput || "Not provided"; // "Not provided" (unwanted)
const phone2 = phoneInput ?? "Not provided"; // "" (correct)
// User preferences with default values
const userSettings = {
theme: null,
itemsPerPage: 0,
showNotifications: false
};
const theme = userSettings.theme ?? "dark"; // "dark"
const itemsPerPage = userSettings.itemsPerPage ?? 10; // 0 (preserves 0)
const showNotifications = userSettings.showNotifications ?? true; // false (preserves false)Function Default Parameters
function calculateTotal(price, discount) {
// Using || would incorrectly override 0 discount
const discountAmount = discount ?? 0.1; // Uses 10% only if discount is null/undefined
return price - (price * discountAmount);
}
console.log(calculateTotal(100, 0)); // 100 (0 discount applied correctly)
console.log(calculateTotal(100, null)); // 90 (10% default discount applied)API Response Handling
// Simulated API response
const userData = {
name: "John",
age: 0, // Age might be 0 (valid)
profile: null // Profile not set
};
// Safe value extraction
const userName = userData.name ?? "Anonymous";
const userAge = userData.age ?? 25; // 0 (not replaced)
const userProfile = userData.profile ?? {}; // {} (null replaced with empty object)When to Use Each Operator
Use ?? (Nullish Coalescing) When:
- You want to provide defaults only for
nullorundefined - You need to preserve meaningful falsy values (
0,false,"") - Working with numeric data where
0is valid - Handling form inputs where empty strings are acceptable
- Dealing with configuration objects with explicit false values
Use || (Logical OR) When:
- You want to provide defaults for any falsy value
- You explicitly want to reject empty strings, zeros, or false values
- Working with boolean flags where all falsy values should be treated the same
- You need backward compatibility with older JavaScript environments
Browser Compatibility
The nullish coalescing operator (??) was introduced in ES2020 and is supported in:
- Node.js 14+
- Chrome 80+, Firefox 72+, Safari 13.1+
- Edge 80+
For older environments, you'll need to use the logical OR (||) or implement a polyfill.
Common Pitfalls and Solutions
// ❌ Problematic code with ||
function updateScore(currentScore, points) {
return currentScore + (points || 1); // Always adds at least 1 point
}
// ✅ Fixed with ??
function updateScoreFixed(currentScore, points) {
return currentScore + (points ?? 1); // Adds 0 if points is 0
}
// Handling nested objects safely
const config = {
settings: {
timeout: null
}
};
// Using optional chaining with nullish coalescing
const timeout = config.settings?.timeout ?? 3000; // 3000Advanced Patterns
Chaining with Optional Chaining
const user = {
preferences: {
theme: null
}
};
// Combined optional chaining and nullish coalescing
const theme = user.preferences?.theme ?? "light";Multiple Fallbacks
// First non-nullish value wins (similar to || but only for null/undefined)
const value = firstOption ?? secondOption ?? thirdOption ?? defaultValue;Performance Considerations
While both operators have similar performance characteristics, ?? can be slightly more efficient in cases where you only need to check for null/undefined since it avoids evaluating all falsy conditions.
Summary Table
| Scenario | || Result | ?? Result | Recommended | |----------|------------|------------|-------------| | null \|\| "default" | "default" | "default" | Either | | undefined \|\| "default" | "default" | "default" | Either | | 0 \|\| "default" | "default" | 0 | ?? | | "" \|\| "default" | "default" | "" | ?? | | false \|\| "default" | "default" | false | ?? | | NaN \|\| "default" | "default" | NaN | ?? |
Conclusion
The nullish coalescing operator (??) provides a more precise tool for handling default values by specifically targeting only null and undefined values. In most modern JavaScript development, ?? should be your default choice for providing fallback values, as it preserves intentional falsy values that might be meaningful in your application logic.
Reserve the logical OR (||) for cases where you explicitly want to replace all falsy values or when you need to support older JavaScript environments that don't support the nullish coalescing operator.
Best Practice
Default to using ?? for most default value scenarios, as it avoids unexpected overrides of meaningful falsy values like 0, false, and empty strings.