Truthy and Falsy Values in JavaScript
Truthy and falsy values in JavaScript are not about what a value looks like. They are about what happens when JavaScript coerces that value to a boolean. That is why [] is truthy, "false" is truthy, and 0 is falsy. The rules are small, but they sit under almost every if, while, ? :, &&, and || you write.
The mistake is using truthiness when you really meant a more specific check.
The everyday falsy list
These values become false in a boolean context:
| Value | Why it matters |
|---|---|
false | Already a boolean false |
0 and -0 | Numeric zero |
0n | BigInt zero |
"" | Empty string |
null | Intentional absence |
undefined | Missing or unassigned value |
NaN | Failed numeric result |
In browsers, document.all is a legacy special case that is also falsy. You will almost never use it, but it exists, because the web has a long memory and not all of it is pleasant.
Everything else is truthy.
Boolean(false); // false
Boolean(0); // false
Boolean(""); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
Boolean("0"); // true
Boolean("false"); // true
Boolean([]); // true
Boolean({}); // true
The empty array trap
Developers often expect empty arrays and empty objects to be falsy because they feel empty. JavaScript does not care how they feel.
const users = [];
if (users) {
console.log("This runs");
}
An array is an object, and objects are truthy. Check the thing you actually care about:
if (users.length > 0) {
console.log("There are users");
}
For plain objects, check keys:
const settings = {};
if (Object.keys(settings).length > 0) {
console.log("Settings exist");
}
Truthy checks are broad checks
This code is common:
if (username) {
renderProfile(username);
}
It means "render if username is not falsy." That excludes "", null, and undefined, which is often fine.
But a truthy check may reject valid data:
function showScore(score) {
if (score) {
return `Score: ${score}`;
}
return "No score yet";
}
showScore(0); // "No score yet"
If 0 is a real score, the check is wrong. Use a narrower condition:
function showScore(score) {
if (score !== null && score !== undefined) {
return `Score: ${score}`;
}
return "No score yet";
}
Or use nullish coalescing when you want to treat only null and undefined as missing.
|| versus ??
The || operator returns the right-hand value when the left-hand value is falsy:
const pageSize = requestedPageSize || 20;
That works if every falsy value should fall back. It fails if 0 or "" are valid:
const maxItems = 0;
const limit = maxItems || 10;
console.log(limit); // 10
?? falls back only for null or undefined:
const maxItems = 0;
const limit = maxItems ?? 10;
console.log(limit); // 0
Use || for "any falsy value should use the default." Use ?? for "only missing values should use the default."
&& returns a value, not a boolean
&& is often used as a guard:
user && renderUser(user);
It does not return true or false by default. It returns one of the original values.
"Ada" && "active"; // "active"
"" && "active"; // ""
That can be useful, but be deliberate. If you need a real boolean, convert it:
const hasUser = Boolean(user);
const alsoHasUser = !!user;
Boolean(value) is clearer for teaching. !!value is common in codebases that prefer terseness.
Ternaries depend on the same rules
The JavaScript ternary operator uses the same truthy and falsy coercion:
const label = count ? `${count} items` : "No items";
Again, this treats 0 as "No items." That is probably right for a cart count. It might be wrong for a score, volume setting, or explicit numeric filter.
Key Takeaways
- Falsy values include
false, numeric zero, BigInt zero, empty string,null,undefined, andNaN. - Empty arrays and empty objects are truthy because all normal objects are truthy.
- Truthy checks are broad. Use explicit comparisons when
0,"", orfalseare valid data. ||falls back on any falsy value.??falls back only onnullorundefined.- Boolean coercion is useful, but it should match the exact meaning your code needs.