Skip to content

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 (null or undefined)

TIP

JavaScript falsy values include: false, 0, -0, 0n, "", null, undefined, and NaN

Behavior Comparison

js
// 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:

js
// 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

js
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

js
// 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 null or undefined
  • You need to preserve meaningful falsy values (0, false, "")
  • Working with numeric data where 0 is 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

js
// ❌ 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; // 3000

Advanced Patterns

Chaining with Optional Chaining

js
const user = {
  preferences: {
    theme: null
  }
};

// Combined optional chaining and nullish coalescing
const theme = user.preferences?.theme ?? "light";

Multiple Fallbacks

js
// 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.