We often run into scenarios where we need to provide default values for variables. Two operators that can help with this are the logical OR (||) and the nullish coalescing (??) operators. While they might appear to behave similarly, they serve distinct purposes and understanding their differences is import for writing bug-free code.

An Example

Consider the following code snippet:

1
2
3
4
5
let userPreference = null;
let defaultPreference = "dark mode";

let theme = userPreference || defaultPreference;
console.log(theme); // Output: "dark mode"

In this example, the || operator is used to provide a default value if userPreference is null or undefined. The code works as expected and outputs "dark mode". Now, let’s tweak userPreference to an empty string:

1
2
3
4
5
let userPreference = "";
let defaultPreference = "dark mode";

let theme = userPreference || defaultPreference;
console.log(theme); // Output: "dark mode"

This output might be surprising because an empty string ("") is a valid value. However, the || operator considers it a falsy value and falls back to defaultPreference.

The ?? Operator

To address this issue, JavaScript introduced the nullish coalescing operator (??). This operator only falls back to the default value if the left-hand side is null or undefined.

Rewriting the previous example using ??:

1
2
3
4
5
let userPreference = "";
let defaultPreference = "dark mode";

let theme = userPreference ?? defaultPreference;
console.log(theme); // Output: ""

Here, theme correctly retains the value of userPreference since an empty string is neither null nor undefined.

Key Differences

  1. Falsy Values:

    • ||: Falls back if the left-hand side is any falsy value (e.g., false, 0, "", null, undefined, NaN).
    • ??: Falls back only if the left-hand side is null or undefined.
  2. Use Cases:

    • ||: Use when you want to handle any falsy value.
    • ??: Use when you want to handle specifically null or undefined.

Practical Examples

  1. Handling User Input:

    1
    2
    3
    4
    5
    6
    7
    8
    
    let userInput = 0;
    let defaultValue = 10;
    
    let value = userInput || defaultValue;
    console.log(value); // Output: 10
    
    value = userInput ?? defaultValue;
    console.log(value); // Output: 0
    

    When the user input is 0, which is a valid number, the || operator falls back to defaultValue, while the ?? operator correctly retains userInput.

  2. Configuration Settings:

    1
    2
    3
    4
    5
    6
    
    function getConfig(config) {
      return config.debug ?? true;
    }
    
    console.log(getConfig({ debug: false })); // Output: false
    console.log(getConfig({ debug: null })); // Output: true
    

    This example ensures that debug is set to true only if it is null or undefined, not just any falsy value.