In a boolean context (an if, &&, ||, !), every value is treated as either truthy or falsy. There are exactly 8 falsy values — everything else is truthy.
The falsy values: , , , (BigInt zero), (empty string), , , .
In a boolean context (an if, &&, ||, !), every value is treated as either truthy or falsy. There are exactly 8 falsy values — everything else is truthy.
The falsy values: , , , (BigInt zero), (empty string), , , .
false0-00n""nullundefinedNaNif ("") {} // skipped — empty string is falsy
if (0) {} // skipped
if ("0") {} // RUNS — non-empty string is truthy!
if ([]) {} // RUNS — empty array is truthy!
if ({}) {} // RUNS — empty object is truthy!
The surprises: "0", [], and {} are all truthy, even though they feel "empty."
const name = input || "guest"; // ❌ if input is "" or 0, falls back to "guest"
const count = input ?? 0; // ✅ ?? only falls back on null/undefined
|| falls back for any falsy value, so a valid 0 or "" gets replaced. The nullish coalescing operator ?? falls back only for null/undefined, which is usually what you actually want.
Knowing the exact falsy set prevents subtle bugs — especially guarding numbers (if (count > 0) not if (count)) and choosing ?? vs || for defaults.