Difference between nullish coalescing (??) and logical OR (||).
|| falls back when the left side is FALSY (0, '', false, NaN, null, undefined). ?? falls back ONLY when the left side is null or undefined. Use ?? for defaults when 0, '', or false are valid values — || would wrongly discard them.
Both pick a fallback value, but they differ in what counts as 'missing.'
Logical OR (||)
a || b → returns b if a is falsy. The falsy values are: false, 0, -0, "", NaN, null, undefined.
0 || "default" // "default" ← 0 is falsy
"" || "default" // "default" ← "" is falsy
false || "default" // "default"
null || "default" // "default"Nullish coalescing (??)
a ?? b → returns b only if a is null or undefined ("nullish"). Everything else — including 0, "", false — passes through.
0 ?? "default" // 0 ← 0 is NOT nullish
"" ?? "default" // "" ← "" is NOT nullish
false ?? "default" // false
null ?? "default" // "default"
undefined ?? "default" // "default"Why it matters — the bug ?? fixes
|| is dangerous for defaults when 0, "", or false are valid values:
// ❌ user explicitly set quantity to 0 — but || throws it away
const quantity = input.quantity || 1; // 0 becomes 1!
// ✅ ?? only defaults when quantity is actually missing
const quantity = input.quantity ?? 1; // 0 stays 0Same trap with count || 10, name || "Anonymous" (empty string is a real name choice?), isEnabled || true (can never be false!).
Rule of thumb: use ?? for defaults/fallbacks; use || only when you genuinely want any falsy value to trigger the fallback.
The syntax gotcha
You can't mix ?? with || or && without parentheses — it's a syntax error, deliberately, to force you to be explicit:
a ?? b || c // SyntaxError
(a ?? b) || c // OKIt also pairs with optional chaining: obj?.value ?? "default".
The framing
"|| falls back on any falsy value — 0, '', false, NaN, plus null/undefined. ?? falls back only on null or undefined. The reason ?? exists: || silently discards valid falsy values, so quantity || 1 turns a real 0 into 1. So I default with ??, and reach for || only when I actually want every falsy value to trigger the fallback. And you must parenthesize when mixing ?? with ||/&&."
Follow-up questions
- •Which values are nullish vs falsy?
- •Give a real bug caused by using || for a default.
- •Why is mixing ?? and || a syntax error?
- •How does ?? combine with optional chaining?
Common mistakes
- •Using || for defaults when 0, '', or false are valid values.
- •Thinking ?? falls back on all falsy values — it's only null/undefined.
- •Mixing ?? with || or && without parentheses.
- •Using ?? when you actually do want '' or 0 to trigger the fallback.
Performance considerations
- •No performance difference — both short-circuit. This is purely about correctness of intent.
Edge cases
- •NaN — falsy (triggers ||) but not nullish (doesn't trigger ??).
- •Document the intent: sometimes you DO want || behavior.
- •?? with a property that might be missing vs explicitly null.
Real-world examples
- •Default function parameters / config values where 0 or '' are legitimate.
- •Form inputs where an empty string or false is a real user choice.