What you'll be able to do
By the end of this page you should be able to predict whether an if will run when you pass a name, a count, or an empty box — without guessing. You will know the short list of falsy values, why "0" and "false" still count as true, and when if (name) is a sloppy stand-in for the question you actually meant.
Previous post: operators and equality.
Who this is for
- People who wrote
if (name)and could not see why a blank input skipped the greeting - Beginners who hid a “0 items” message because
if (count)is false when count is0 - Anyone who thought
if (name)meantif (name === true)
You can skip this if you already list the falsy values from memory, you check name.trim().length for text, and you never use if (count) when zero is a real answer. Come back when a branch “should have run” and the value was empty, zero, or null.
if does not ask “is this true?” — it asks “is this truthy?”
When you write if (value), JavaScript converts value to a boolean behind the scenes, then decides. That conversion is called boolean coercion. Values that become false are falsy. Everything else is truthy.
const name = "Asha";
if (name) {
console.log("We have a name.");
}
Scenario A — a real name. "Asha" is truthy, so the block runs. That is why if (name) feels convenient.
Scenario B — you meant a boolean. if (name === true) is a different question. "Asha" === true is false. So if (name) can pass while if (name === true) fails. One checks “does this look filled in?” The other checks “is this the boolean true?” Do not mix them up in your head.
You can see the conversion with Boolean(...) or with a double not, !!value, which is a common shortcut:
console.log(Boolean("Asha"));
console.log(Boolean(""));
console.log(!!0);
That prints true, false, false. !! is not magic — it is “convert to boolean, then convert again,” which leaves you with a real true or false.
The falsy list (short, worth memorizing)
These become false in an if:
false0(and-0)""(empty string)nullundefinedNaN
That is almost the whole set you will meet as a beginner. (0n is bigint zero — skip it until you need bigint.)
console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(NaN));
Scenario A — an empty form. input.value for a blank box is "". if (input.value) skips. That is often what you wanted: “do not greet until they type something.”
Scenario B — a count that is allowed to be zero. if (count) when count is 0 also skips. Then your UI never shows “0 clips left,” and it looks like the feature is broken. Zero is a real number. Check count === 0 or count > 0 on purpose, not “is count truthy?”
null and undefined are falsy too. Scenario A: a function that did not return gives undefined. Scenario B: a missing user object you set to null on purpose. if (user) is a rough “did we get someone?” check. It is not a deep validation of user.name.
Truthy surprises: "0", "false", and spaces
Most non-empty strings are truthy — including strings that look like false values.
console.log(Boolean("0"));
console.log(Boolean("false"));
console.log(Boolean(" "));
All three are true.
Scenario A — a form that sent the text "0". if (raw) passes. if (Number(raw)) fails, because Number("0") is 0, which is falsy. Same box, two checks, two answers. Convert first, then ask the question that matches the type.
Scenario B — spaces in a name field. " " is not empty. if (name) passes, then you render Hello, . Trim first: const cleaned = name.trim(); if (cleaned) — or better, if (cleaned.length === 0) when you want the empty case to be obvious.
Arrays and objects are truthy even when they look empty: Boolean([]) and Boolean({}) are true. You do not need that much this week, but it stops you from writing if (list) thinking that means “the list has items.” For items, check list.length.
&& and || follow the same truthy rules
&& means “and.” || means “or.” They do not only return true/false — they return one of the original values, using truthiness to decide which.
const name = "";
const label = name || "Guest";
console.log(label);
Scenario A — a fallback name. Empty string is falsy, so name || "Guest" becomes "Guest". Handy for a placeholder.
Scenario B — a fallback that eats zero. count || 10 when count is 0 becomes 10, because zero is falsy. You wanted “use 10 only if count is missing,” and you wiped a real zero. That is the classic || default bug. The next post covers ??, which treats only null and undefined as missing — a better default for numbers.
For if conditions, && and || still read as and/or:
if (cleaned && cleaned.length > 1) {
console.log("Name looks long enough.");
}
If cleaned is "", the right side never runs. That short-circuit is useful, and it is also why a falsy left side can hide a bug on the right.
A tiny practice file
Save as truthy.html. Try Asha, then a blank box, then spaces, then 0.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Truthy</title>
</head>
<body>
<input id="raw" placeholder="Type a name or 0" />
<button id="go">Test if (value)</button>
<p id="out">Result will show here.</p>
<script>
const rawInput = document.getElementById("raw");
const goButton = document.getElementById("go");
const out = document.getElementById("out");
goButton.addEventListener("click", function () {
const raw = rawInput.value;
const trimmed = raw.trim();
const asNumber = Number(raw);
out.textContent =
"if (raw): " +
Boolean(raw) +
". if (trimmed): " +
Boolean(trimmed) +
". if (Number(raw)): " +
Boolean(asNumber) +
". trimmed.length: " +
trimmed.length;
});
</script>
</body>
</html>
A blank box makes if (raw) false. Spaces make if (raw) true and if (trimmed) false. 0 makes if (raw) true (it is the string "0") and if (Number(raw)) false. That three-way split is the whole lesson in one click.
Mistakes I see a lot
1. if (name) when you meant “non-empty after trim.” Spaces will pass. Trim, then check length.
2. if (count) when zero is valid. Use count === 0 or count > 0.
3. Thinking if (name) equals if (name === true). Strings are not the boolean true.
4. Using value || fallback for a number that can be 0. Zero looks missing. Wait for ?? in the next post, or check value === undefined.
5. if (list) to mean “has items.” Empty arrays are truthy. Use list.length.
6. Forgetting NaN is falsy. A failed Number("hello") skips if (n) the same way 0 does — which is why Number.isNaN still matters.
What to try before the next post
- Log
Boolean(""),Boolean(" "),Boolean("0"), andBoolean(0). - Log
Boolean([])and think aboutif (list). - In the console, set
count = 0and trycount || 10. - Build the tiny HTML file and try a name, spaces, and
0.
Next in this series: optional chaining and nullish coalescing — ?. so nested reads do not crash, and ?? so a real 0 is not treated as missing.
Try this next outside the series
Values become easier when you see them inside real forms and payloads, not only tiny console lines.
- React forms without pain — see strings, numbers, and booleans show up in UI work
- JSON Formatter — inspect values and nesting the way APIs hand them back