Booleans & truthiness
Learn true and false, compare values, convert truthy and falsy inputs, avoid == true traps, and use booleans in practical JavaScript.
- 01Read boolean answersRecognize primitive
trueandfalse, and spot booleans produced by comparisons, methods, and!. - 02Predict truthinessUse the exact falsy list, then explain tricky truthy values like
"false",[], andnew Boolean(false). - 03Write safer conditionsConvert values deliberately, avoid
== true, and choose practical patterns for toggles, arrays, forms, and URL strings.
true and false
A boolean is JavaScript's smallest yes/no answer. There are only two primitive boolean values: true and false. You will see them in variables with names like isOpen, hasItems, isLoggedIn, and checked.
const isOpen = true;const hasItems = false;console.log(typeof true);console.log(isOpen);console.log(hasItems);Line 3 prints "boolean" because true is a primitive boolean, not a string. Lines 4 and 5 print the values stored in yes/no variables. The variable names are not required, but names that start with is, has, or can make boolean code easy to read.
A boolean is exactly true or false. A value is truthy when JavaScript treats it like true in a condition, and falsy when JavaScript treats it like false.
Imagine a guest list with only a few names on the no list. Those names are no; everyone else is yes. Truthiness works the same way with its eight falsy values.
- In real life: Names on the short no list
- In JavaScript: The exact falsy values
- In real life: Everyone else comes in
- In JavaScript: Every other ordinary value is truthy
- In real life: The word false on a name tag
- In JavaScript: The string
"false"is truthy
Where the analogy stops: A real guest list can change. JavaScript uses the same built-in falsy list every time.
This lesson stays focused on booleans. The engine-side story is in Booleans inside the engine. The later Booleans, null & undefined lesson compares booleans with the two common missing-value markers side by side.
Where booleans come from
STEP THROUGHBeginners often write true and false directly first. Soon after, booleans start coming from questions: comparisons, methods that ask yes/no questions, and the not operator !.
Step through the ordinary places beginners first meet booleans: literal values, comparisons, method questions, and !.
script
const hasItems = false;const trueType = typeof true;const bigger = 5 > 3;const sameLetter = "a" === "A";const hasEll = "hello".includes("ell");const isArray = Array.isArray([]);const isReallyNaN = Number.isNaN(NaN);const startsWithC = "cat".startsWith("c");const isClosed = !isOpen;console.log(isOpen, hasItems, trueType);console.log(bigger, sameLetter);console.log(hasEll, isArray, isReallyNaN, startsWithC);console.log(isClosed);Read the names out loud. bigger asks whether 5 > 3. hasEll asks whether the string contains a piece of text. isArray asks whether a value is an array. isClosed flips isOpen with !.
Boolean conversion: Boolean(), !!, if, and !
STEP THROUGHSometimes you already have a value and you want to know how JavaScript will treat it in a condition. Use Boolean(value) for the explicit answer. You will also see !!value, which uses two not operators to end up with the same primitive boolean.
Compare Boolean(value), !!value, !value, and the branch chosen by if (value).
script
const explicit = Boolean(value);const compact = !!value;const flipped = !value;if (value) { console.log("truthy branch");} else { console.log("falsy branch");}console.log(explicit, compact, flipped);if (value) uses the same conversion to choose a branch. It does not change the original value. One ! flips the answer; two !! flips it back to the truthiness answer.
The eight falsy values
The everyday falsy list is short and exact. Memorize these eight values; every other ordinary JavaScript value is truthy.
false0-00n""nullundefinedNaN
Browsers also give the old legacy object document.all special falsy behavior through ECMAScript Annex B's [[IsHTMLDDA]]. Treat that as compatibility trivia, not a normal value to use. The engine-side details fit better in Null inside the engine.
The surprises are all on the truthy side: "0", "false", " ", [], , functions, symbols, and wrapper objects all pass a truthiness check.
Truthiness playground
48 VALUESTry many values and expressions. The playground shows Boolean(value), !!value, and the branch chosen by if (value). The computed-expression group includes classic bugs such as "abc".indexOf("a") returning 0 and floating-point math leaving a tiny truthy number.
const value = "0";console.log(Boolean(value));console.log(!!value);if (value) { console.log("truthy branch");} else { console.log("falsy branch");}A non-empty string is truthy, even when it contains the character zero.
"0" is truthy. Boolean(value) is true, !!value is true, and if (value) chooses the truthy branch. A non-empty string is truthy, even when it contains the character zero.
false0-00n""nullundefinedNaN"0""false"" "[]{}[""][[]]function () {}Symbol()1n-1Infinitynew Boolean(false)new Number(0)new String("")/(?:)/
Sort each card using JavaScript’s exact truthiness rules. Watch for empty-looking objects and wrapper objects.
Here is every value from the playground at once, grouped the same way: empty values, strings, numbers, BigInts, objects, wrapper objects, and computed expressions. The middle column is computed from the real value when the page is built, not typed by hand.
| Value | Reads as | Why |
|---|---|---|
true | truthy | true is already a boolean, so conversion leaves it as true. |
false | falsy | The boolean false is falsy by definition. |
null | falsy | null means intentionally empty, and it is on the falsy list. |
undefined | falsy | undefined means no value was supplied, and it is on the falsy list. |
void 0 | falsy | void always produces undefined, so this is falsy too. |
"" | falsy | Only the string with zero characters is falsy. |
"0" | truthy | A non-empty string is truthy, even when it contains the character zero. |
"false" | truthy | JavaScript does not read the English word inside the string. |
" " | truthy | A space is a character, so the string is not empty. |
"\n" | truthy | A newline character still counts as one character. |
"null" | truthy | This is text, not the null value. |
"undefined" | truthy | Text that spells undefined is still a non-empty string. |
"NaN" | truthy | This is a string, not the special numeric NaN value. |
0 | falsy | Number zero is falsy. |
-0 | falsy | Negative zero is still zero for truthiness. |
NaN | falsy | NaN is the one falsy not-a-number value. |
-1 | truthy | Any non-zero number is truthy, even a negative one. |
0.1 | truthy | Any non-zero decimal number is truthy. |
Infinity | truthy | Infinity is a number value and it is truthy. |
-Infinity | truthy | Negative infinity is also a non-zero number value, so it is truthy. |
0n | falsy | BigInt zero is falsy. |
1n | truthy | Non-zero BigInts are truthy. |
-1n | truthy | Negative BigInts are truthy unless they are exactly 0n. |
[] | truthy | Arrays are objects, and every ordinary object is truthy. |
({}) | truthy | Objects are truthy even when they have no properties. |
[0] | truthy | The array object is truthy even though its first item is falsy. |
[""] | truthy | The array is an object, so the falsy item inside does not make the array falsy. |
[[]] | truthy | A nested array is still an object held inside another truthy array. |
function () {} | truthy | Functions are objects, and objects are truthy. |
() => {} | truthy | Arrow functions are function objects, so they are truthy. |
Symbol() | truthy | Every Symbol value is truthy. |
new Date(0) | truthy | Date objects are objects, so they are truthy. |
/(?:)/ | truthy | Regular expression objects are truthy. |
new Boolean(false) | truthy | The wrapper object is truthy even though the primitive inside is false. |
new Number(0) | truthy | A Number wrapper is an object, so it is truthy. |
new String("") | truthy | A String wrapper is an object, so it is truthy even when it wraps empty text. |
"abc".indexOf("a") | falsy | A found index can be 0, which is falsy. This is a classic indexOf bug. |
"".length | falsy | The empty string has length zero, and zero is falsy. |
Number("") | falsy | Converting an empty string to a number gives 0, which is falsy. |
Number("abc") | falsy | A failed numeric conversion produces NaN, which is falsy. |
parseInt("px") | falsy | No leading digits means parseInt returns NaN, a falsy value. |
1e-400 | falsy | This tiny number underflows to 0, so it is falsy. |
0 * -1 | falsy | The calculation creates -0, and -0 is falsy. |
[].length | falsy | An empty array is truthy, but its length is the falsy number 0. |
" ".trim() | falsy | Trimming two spaces produces the empty string, which is falsy. |
[1, 2].find((n) => n > 5) | falsy | When find finds nothing, it returns undefined, which is falsy. |
5 - 5 | falsy | The result is numeric zero, so it is falsy. |
0.1 + 0.2 - 0.3 | truthy | Floating-point rounding leaves a tiny non-zero number, so it is truthy. |
Booleans in conditions and logic
Conditions use truthiness. The ! operator returns a primitive boolean. The logical operators && and || are a little different: they choose and return one of their original operands. The full lesson is Logical operators; here is the beginner preview.
const name = "";const fallback = name || "friend";const subscribed = true;const access = subscribed && "member area";console.log(fallback);console.log(access);console.log(!subscribed);Line 2 returns the fallback string because name is the empty string. Line 4 returns the string "member area", not the boolean true. Line 7 uses !, so it prints a real boolean.
Boolean objects and equality traps
TRAPSBoolean(x) without new returns a primitive boolean. new Boolean(false) creates an object wrapper. Objects are truthy, so the wrapper is dangerous in conditions.
const boxed = new Boolean(false);console.log(Boolean(boxed));console.log(typeof boxed);console.log(boxed.valueOf());console.log(Boolean(false));If you need a boolean, write true, false, Boolean(value), or a comparison. Avoid new Boolean(...), new Number(...), and new String(...) for beginner application code.
A second trap is comparing values with == true or == false. When loose equality sees a boolean, it converts toward numbers. That creates surprising results.
console.log("1" == true);console.log("true" == true);console.log([] == false);console.log(Boolean([]));| Value | Boolean(value) | value == true | value == false |
|---|---|---|---|
"1" | true | true | false |
"true" | true | false | false |
[] | true | false | true |
0 | false | false | true |
"false" | true | false | false |
Prefer if (value) when you mean “truthy,” or value === true when you require the primitive boolean true exactly.
Practical booleans
Booleans show up in interface state, form controls, array checks, filters, and URL parsing. The pattern depends on what question you are asking.
- Toggles: flip a boolean with
isOpen = !isOpen. - Form controls: a checkbox exposes a boolean
.checkedproperty. - Arrays: use
if (items.length)to ask whether the list has items. - Cleanup:
array.filter(Boolean)removes falsy values, including0. - Strings from URLs or forms: parse
"true"and"false"with exact comparisons.
let isOpen = false;isOpen = !isOpen;console.log(isOpen);const checkbox = { checked: true };console.log(checkbox.checked);const items = ["hat", "coat"];if (items.length) { console.log("show cart");}const mixed = [0, 1, "", "Ada", null, false, true];console.log(mixed.filter(Boolean).join("|"));const fromUrl = "false";console.log(Boolean(fromUrl));console.log(fromUrl === "true");console.log(fromUrl === "false" ? false : fromUrl === "true");Common misconceptions
- “The string
"false"is false.” It is a non-empty string, so it is truthy. - “Whitespace is empty.”
" "and"\n"contain characters and are truthy. - “Empty arrays and objects are falsy.” They are objects, and ordinary objects are truthy.
- “
new Boolean(false)behaves likefalse.” It is an object, so it is truthy. - “
== truechecks truthiness.” It follows loose-equality conversions instead. - “
filter(Boolean)only removes missing values.” It removes every falsy value, including0. - “
if (value)is a missing-value check.” It also rejectsfalse,0,"", andNaN.
Practice exercises
6 EXERCISESPredict the four outputs in order.
console.log(typeof true);
console.log(5 > 3);
console.log("a" === "A");
console.log(!"hello".includes("z"));The outputs are boolean, true, false, and true. Comparisons and ! produce primitive booleans.
How many values are on the exact falsy list?
const falsy = [false, 0, -0, 0n, "", null, undefined, NaN];
console.log(falsy.length);
console.log(falsy.every((value) => !value));The list contains 8 values, and every one is falsy.
The URL gave you the string "false". What should the exact comparison print?
const raw = "false";
console.log(Boolean(raw));
console.log(raw === "true");const raw = "false";
console.log(Boolean(raw));
console.log(raw === "true");For raw = "false", raw === "true" prints false. The string itself is truthy, so Boolean(raw) is not a parser.
What does the filtered list print?
const values = [0, 1, 2, "", "ok", null, false, true];
console.log(values.filter(Boolean).join("|"));The filtered list prints 1|2|ok|true. Use a narrower callback if 0 or false is valid data.
The code prints missed even though "a" is in the string. Why?
const position = "abc".indexOf("a");
if (position) {
console.log("found");
} else {
console.log("missed");
}indexOf returned 0, so the if (position) check went to the falsy branch. Use position !== -1 or includes.
Predict the three outputs.
const boxed = new Boolean(false);
console.log(Boolean(boxed));
console.log(typeof boxed);
console.log(Boolean(false));The wrapper object is truthy and has type object; the primitive false stays falsy. The outputs are true, object, false.
Check your understanding
8 QUESTIONSQuestion 1 of 8How many primitive boolean values does JavaScript have?
Choose an answer to see the explanation.
Question 2 of 8What do the comparison and method print?
Read the code, then predictconsole.log(5 > 3); console.log("hello".includes("z"));Choose an answer to see the explanation.
Question 3 of 8What does this print?
Read the code, then predictconsole.log(Boolean("false"));Choose an answer to see the explanation.
Question 4 of 8What do the empty and space strings print?
Read the code, then predictconsole.log(Boolean("")); console.log(Boolean(" "));Choose an answer to see the explanation.
Question 5 of 8What does this array check print?
Read the code, then predictconsole.log(Boolean([])); console.log([].length === 0);Choose an answer to see the explanation.
Question 6 of 8What do these loose equality checks print?
Read the code, then predictconsole.log("1" == true); console.log("true" == true);Choose an answer to see the explanation.
Question 7 of 8What does a Boolean object do?
Read the code, then predictconst value = new Boolean(false); console.log(Boolean(value)); console.log(typeof value);Choose an answer to see the explanation.
Question 8 of 8What does this tiny number print?
Read the code, then predictconsole.log(Boolean(0.1 + 0.2 - 0.3));Choose an answer to see the explanation.
Key takeaways
- Primitive booleans are exactly
trueandfalse. - Comparisons, yes/no methods, and
!produce primitive booleans. - The everyday falsy list is
false,0,-0,0n,"",null,undefined, andNaN. - Everything else ordinary is truthy, including
"false",[],, andnew Boolean(false). - Avoid
== true; useif (value)for truthiness orvalue === truefor the exact primitive. - Use practical checks carefully:
items.length,filter(Boolean), andraw === "true"each answer different questions.
Final definition: a boolean is the primitive yes/no value true or false; truthiness is JavaScript's automatic boolean reading of any value.
Up next: undefined, the value JavaScript uses when something has not been supplied yet.