Every value in JavaScript is either "truthy" or "falsy" when it's evaluated in a boolean context — like the condition of an if statement, a while loop, or either side of && and ||. Understanding this is essential, because JavaScript will happily let you put a string, a number, or an object directly inside an if condition without explicitly converting it to true or false first.
The 8 Falsy Values
JavaScript has exactly eight falsy values. Everything else in the entire language is truthy.
// The 8 falsy values:
false
0
-0
0n // BigInt zero
"" // empty string
null
undefined
NaN
That means even things that feel "empty" — like an empty array [] or an empty object {} — are actually truthy, which surprises a lot of developers coming from other languages.
if ([]) {
console.log("Empty array is truthy!");
}
if ({}) {
console.log("Empty object is truthy!");
}
if ("0") {
console.log('The string "0" is truthy — only the empty string is falsy!');
}
Output:
Empty array is truthy!
Empty object is truthy!
The string "0" is truthy — only the empty string is falsy!
Truthiness in Short-Circuit Operators
&& and || don't actually return true/false — they return one of their original operand values, based on truthiness. This is used constantly for default values and conditional rendering.
const username = "";
const displayName = username || "Guest"; // "" is falsy, so this falls back
console.log(displayName);
const isLoggedIn = true;
isLoggedIn && console.log("Showing dashboard..."); // only runs if truthy
Output:
Guest
Showing dashboard...
The Nullish Coalescing Operator (??) as a Safer Alternative
The || fallback pattern has a gotcha: it treats 0, "", and false as "missing" too, even when they're legitimate values you meant to keep. The ?? operator only falls back on null or undefined specifically:
const quantity = 0;
console.log(quantity || 10); // 10 — wrong! 0 was a real value
console.log(quantity ?? 10); // 0 — correct, only null/undefined trigger the fallback
Output:
10
0
Use ?? whenever a falsy-but-valid value like 0 or "" should be preserved, and reserve || for cases where you genuinely want to treat every falsy value as "use the default instead."
