Docs
README
3.9 Nullish Coalescing Operator
Table of Contents
- ā¢What Is Nullish Coalescing
- ā¢Nullish vs Falsy
- ā¢Comparison with OR Operator
- ā¢Common Use Cases
- ā¢Nullish Coalescing Assignment
- ā¢Combining with Optional Chaining
- ā¢Operator Precedence
What Is Nullish Coalescing
The nullish coalescing operator (??) returns the right-hand operand when the left-hand operand is null or undefined, otherwise returns the left-hand operand.
Syntax
const result = leftExpr ?? rightExpr;
Basic Behavior
// Returns right side only for null/undefined
null ?? 'default'; // "default"
undefined ?? 'default'; // "default"
// Returns left side for everything else (including falsy values!)
0 ?? 'default'; // 0
'' ?? 'default'; // ""
false ?? 'default'; // false
NaN ?? 'default'; // NaN
Visual Representation
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā value ?? default ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā Is value null or undefined? ā
ā ā ā
ā āāāāā“āāāā ā
ā ā ā ā
ā YES NO ā
ā ā ā ā
ā ā¼ ā¼ ā
ā return return ā
ā default value ā
ā ā
ā Only null and undefined trigger the default! ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Nullish vs Falsy
Understanding the Difference
Nullish values: Only null and undefined
Falsy values: null, undefined, 0, "", false, NaN
// Falsy values in JavaScript
Boolean(null); // false - also nullish
Boolean(undefined); // false - also nullish
Boolean(0); // false - NOT nullish
Boolean(''); // false - NOT nullish
Boolean(false); // false - NOT nullish
Boolean(NaN); // false - NOT nullish
Comparison Table
| Value | Is Falsy? | Is Nullish? | || returns default | ?? returns default |
|---|---|---|---|---|
null | ā | ā | ā | ā |
undefined | ā | ā | ā | ā |
0 | ā | ā | ā | ā |
"" | ā | ā | ā | ā |
false | ā | ā | ā | ā |
NaN | ā | ā | ā | ā |
Comparison with OR Operator
The Problem with OR (||)
// OR returns the right side for any falsy value
const count = 0;
const displayCount = count || 'No items';
console.log(displayCount); // "No items" - WRONG! We wanted 0!
const name = '';
const displayName = name || 'Anonymous';
console.log(displayName); // "Anonymous" - But empty string was intentional!
The Solution with Nullish Coalescing (??)
// ?? only returns right side for null/undefined
const count = 0;
const displayCount = count ?? 'No items';
console.log(displayCount); // 0 - Correct!
const name = '';
const displayName = name ?? 'Anonymous';
console.log(displayName); // "" - Respects empty string!
Side-by-Side Comparison
const examples = [null, undefined, 0, '', false, 'hello'];
console.log('Value\t\t|| result\t?? result');
console.log('ā'.repeat(40));
examples.forEach((val) => {
const orResult = val || 'default';
const nullishResult = val ?? 'default';
console.log(`${String(val)}\t\t${orResult}\t\t${nullishResult}`);
});
// Output:
// Value || result ?? result
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
// null default default
// undefined default default
// 0 default 0
// default
// false default false
// hello hello hello
When to Use Each
| Use Case | Use ?? | Use || |
|---|---|---|
| Default for missing data | ā | |
| Default for any falsy value | ā | |
Preserving 0 as valid | ā | |
Preserving "" as valid | ā | |
Preserving false as valid | ā | |
| Fallback for "empty" values | ā |
Common Use Cases
1. Function Default Parameters
// ?? is better for optional parameters with valid falsy values
function createUser(name, age, isActive) {
return {
name: name ?? 'Guest',
age: age ?? 0, // 0 is a valid age!
isActive: isActive ?? true, // false is a valid status!
};
}
console.log(createUser('John', 0, false));
// { name: "John", age: 0, isActive: false }
console.log(createUser('John'));
// { name: "John", age: 0, isActive: true }
2. Configuration Objects
const userConfig = {
theme: 'dark',
fontSize: 0, // User wants smallest size
showTips: false, // User disabled tips
};
const defaultConfig = {
theme: 'light',
fontSize: 14,
showTips: true,
};
// With ?? - respects 0 and false
const config = {
theme: userConfig.theme ?? defaultConfig.theme,
fontSize: userConfig.fontSize ?? defaultConfig.fontSize,
showTips: userConfig.showTips ?? defaultConfig.showTips,
};
console.log(config);
// { theme: 'dark', fontSize: 0, showTips: false }
3. API Response Handling
function displayUserInfo(response) {
const name = response.data?.user?.name ?? 'Unknown User';
const postCount = response.data?.user?.posts ?? 0;
const bio = response.data?.user?.bio ?? 'No bio provided';
return `${name} has ${postCount} posts. Bio: ${bio}`;
}
// Works correctly even with empty strings or zero
const response = {
data: {
user: {
name: 'John',
posts: 0, // New user, no posts yet
bio: '', // Empty bio
},
},
};
console.log(displayUserInfo(response));
// "John has 0 posts. Bio: " (preserves 0 and "")
4. Chained Nullish Coalescing
const a = null;
const b = undefined;
const c = 0;
const d = 'value';
// Returns first non-nullish value
const result = a ?? b ?? c ?? d;
console.log(result); // 0 (c is first non-nullish)
Nullish Coalescing Assignment
Basic Syntax (??=)
The nullish coalescing assignment operator assigns the right-hand value only if the left-hand variable is nullish.
let x = null;
x ??= 'default';
console.log(x); // "default"
let y = 0;
y ??= 'default';
console.log(y); // 0 (not reassigned - 0 is not nullish)
Practical Examples
// Initialize optional properties
const settings = {};
settings.theme ??= 'light';
settings.fontSize ??= 14;
settings.volume ??= 50;
console.log(settings);
// { theme: 'light', fontSize: 14, volume: 50 }
// Won't override existing values
settings.theme = 'dark';
settings.theme ??= 'light'; // Won't change
console.log(settings.theme); // 'dark'
Lazy Initialization
let cachedValue;
function getCachedValue() {
cachedValue ??= expensiveComputation();
return cachedValue;
}
function expensiveComputation() {
console.log('Computing...');
return 42;
}
getCachedValue(); // "Computing..." ā 42
getCachedValue(); // Returns 42 (no recomputation)
Combining with Optional Chaining
Perfect Partners
Nullish coalescing (??) and optional chaining (?.) work great together:
const user = {
profile: {
// name is missing
settings: {
notifications: false,
},
},
};
// Safe access with default value
const userName = user?.profile?.name ?? 'Anonymous';
console.log(userName); // "Anonymous"
// Respects false as a valid value
const notifications = user?.profile?.settings?.notifications ?? true;
console.log(notifications); // false (not replaced with default)
Common Pattern
function getConfig(options) {
return {
host: options?.server?.host ?? 'localhost',
port: options?.server?.port ?? 3000,
ssl: options?.server?.ssl ?? false,
timeout: options?.server?.timeout ?? 5000,
};
}
console.log(getConfig({}));
// { host: 'localhost', port: 3000, ssl: false, timeout: 5000 }
console.log(getConfig({ server: { port: 8080, ssl: true } }));
// { host: 'localhost', port: 8080, ssl: true, timeout: 5000 }
Operator Precedence
Precedence Rules
?? has lower precedence than most operators, but there's a special rule:
You cannot directly mix ?? with && or || without parentheses.
// ā SyntaxError - ambiguous without parentheses
// const result = a || b ?? c;
// const result = a && b ?? c;
// ā
Use parentheses to clarify intent
const result1 = (a || b) ?? c; // OR first, then nullish
const result2 = a || (b ?? c); // Nullish first, then OR
const result3 = (a && b) ?? c; // AND first, then nullish
Why This Rule Exists
// Without the rule, this would be ambiguous:
const value = null;
const fallback = false;
const default = "default";
// Does this mean:
// (null || false) ?? "default" ā "default"
// or
// null || (false ?? "default") ā false
Safe Combinations
// Arithmetic operators - OK
const a = null;
const result = (a ?? 0) + 10; // 10
// Comparison operators - OK
const value = null ?? 5;
const isPositive = value > 0; // true
// Ternary operator - OK
const message = (value ?? 0) > 0 ? 'positive' : 'not positive';
Summary
| Aspect | ?? (Nullish Coalescing) | || (Logical OR) |
|---|---|---|
| Triggers on | null, undefined | All falsy values |
Preserves 0 | ā Yes | ā No |
Preserves "" | ā Yes | ā No |
Preserves false | ā Yes | ā No |
| Use for | Null/undefined defaults | Falsy fallbacks |
Quick Reference
// Nullish coalescing
value ?? default // Returns default only for null/undefined
// Nullish assignment
variable ??= value // Assigns only if variable is null/undefined
// With optional chaining
obj?.prop ?? default // Safe access with default
// Must use parentheses with && or ||
(a || b) ?? c // OK
(a && b) ?? c // OK
a || b ?? c // SyntaxError!
Next Steps
After mastering nullish coalescing, proceed to:
- ā¢3.10 Optional Chaining - Safe property access
- ā¢Combine both operators for robust data handling
- ā¢Refactor existing code to use
??where appropriate