Boolean Logic in Javascript: Truthy - Falsy, and Equality Explained for Beginners


Coding isn't just about telling computers what to do; it's about telling them when to do it. — It's about telling them how to make choices. 🧠
Should this run or not? Is this true or false? 🤔
Javascript gives us tools like Boolean logic, conditions, and equality checks to help our programs "decide" what to do.
Having a better understanding of these concepts helps us spend more time building cool stuff and less time chasing mysterious bugs.
In this deep dive, we'll get comfy with:
Boolean values – the language of true and false
Conditional logic – how our code makes decisions
Truthy and falsy – Javascript's "hidden" rules for what counts as true
==
vs===
– the infamous equality operators and their quirks
By the end, we'll think like Javascript does when it comes to decision-making.
Let's get into it. 🚀
Boolean Logic: The Language of Decisions
Boolean logic underpins almost everything in programming. A Boolean is the simplest type of value — it can only be:
true
false
Think of it like a light switch: it's either on (true) or off (false).
Why Booleans Matter
Booleans answer questions in our code:
Is the user logged in? → true or false
Does this number exceed 100? → true or false
Did we finish loading the data? → true or false
They're the yes/no checkpoints that drive all our conditions.
let isLoggedIn = true;
if (isLoggedIn) {
console.log("Welcome back!");
} else {
console.log("Please log in.");
}
Here, isLoggedIn
determines which branch of code to run. Change it to false
, and we get the other path.
Logical Operators: Combining Truths
In programming, we often make decisions that depend on more than one condition.
Logical operators, also known as Boolean operators, enable us to combine and modify conditions, allowing our programs to make more informed decisions. They're essential when we want to check more than one thing at the same time.
AND (
&&
) → Returnstrue
only if both sides aretrue
.OR (
||
) → Returnstrue
if at least one side istrue
.NOT (
!
) → Flips a Boolean:true
→false
,false
→true
.
Example:
let hasTicket = true;
let seatAvailable = false;
console.log(hasTicket && seatAvailable); // false — both must be true
console.log(hasTicket || seatAvailable); // true — at least one is true
console.log(!hasTicket); // false — flips true → false
Short-Circuiting: Why Javascript Doesn't Always Check Everything
Logical operators in Javascript short-circuit, meaning they stop evaluating as soon as the result is clear:
For
&&
, if the first value isfalse
, Javascript won't bother checking the second — the whole thing must befalse
anyway.For
||
, if the first value istrue
, Javascript immediately returns it and skips the second.
This isn't just for speed; we can use it to write cleaner code:
let user = null;
let defaultName = "Guest";
console.log(user || defaultName); // "Guest" — user is null, so fallback applies
And here's a gotcha: logical operators (&&
and ||
) aren't just used to combine conditions and return true
or false
. In Javascript, they often return one of the original values instead of a plain Boolean — there's more going on under the hood!
Conditional Statements: Teaching Code to Choose
Once we have Boolean values, we use conditions to control what happens next.
if
Statements – The Basic Gatekeeper
The simplest decision-maker is if
. It says: "Run this code only if this condition is true."
let age = 20;
if (age >= 18) {
console.log("You’re an adult!");
}
Perfect for simple checks.
if…else
and else if
– Handling Multiple Paths
Sometimes, we need to take different actions based on specific conditions. That's where else and else if come in:
let score = 75;
if (score >= 90) {
console.log("Grade A");
} else if (score >= 75) {
console.log("Grade B");
} else {
console.log("Keep practicing!");
}
Javascript checks each condition in order and stops at the first match.
Tip: Put the most likely conditions first. Too many else if
chains? A switch
might be cleaner.
Real-World Case: Feature Toggles
Imagine we're building an app and want to enable a new feature only for beta users:
let isBetaUser = true;
let featureEnabled = false;
if (isBetaUser && featureEnabled) {
console.log("Enjoy the new feature!");
} else {
console.log("Coming soon!");
}
We're using both Booleans and a condition to control who sees what.
Conditional Gotchas
Truthy and Falsy: Javascript's Hidden Rules
In Javascript, not everything that behaves like true or false is literally the Boolean values true
or false
.
Any value can act as true
(we call it truthy) or false
(falsy) when Javascript expects a Boolean — for example, inside an if
statement, a loop condition, or with logical operators.
This concept can be a bit tricky to grasp at first, but understanding it is crucial for writing reliable conditional code in Javascript.
Think of it like a simple yes/no test: Javascript asks, "Does this value count as something?" If yes → truthy; if no → falsy.
Falsy Values: The Exclusive Seven
Javascript only treats seven specific values as falsy. Everything else counts as truthy. Here they are:
false
— the Boolean value for "no."0
— the number zero. Even though other numbers (positive or negative) are truthy,0
is falsy.""
— an empty string, meaning no characters inside quotes.null
— a deliberate "no value" placeholder.undefined
— a variable exists but hasn't been given a value yet.NaN
— "Not-a-Number," which you get from invalid math like0 / 0
orparseInt("abc")
.0n
— BigInt zero, the BigInt version of0
, also falsy.
Examples:
if (0) console.log("Will this run?"); // No, 0 is falsy.
if ("") console.log("Empty string?"); // Nope, falsy.
if (undefined) console.log("Undefined?"); // Also falsy.
In all three cases, Javascript skips the console.log()
because the values fail the "Does this value count as something?" test.
Everything Else is Truthy
Anything not on that list is truthy — even values that feel "empty" or "false-like" to us:
if ("0") console.log("String containing zero is truthy!");
if ([]) console.log("Even an empty array counts as truthy!");
if ({}) console.log("Empty object? Truthy as well!");
"0"
is a non-empty string, so it's truthy, even if it represents zero.[]
and{}
are objects. In Javascript, all objects are truthy, even when they're empty.
This catches beginners off guard: an empty array (`[]`) or an empty object (`{}`) in an if
check doesn't behave like false
.
How if (value) Works Behind the Scenes
When we write:
if (expression) {
console.log("This runs if value is truthy.");
}
Javascript automatically evaluates the expression
and converts the returned value into a Boolean using a process called type coercion:
If the returned value is one of the seven falsy values, it becomes
false
and the block is skipped.Otherwise, it becomes
true
, and the block runs.
Example:
let name = "Luna";
if (name) {
console.log("Hello, " + name + "!");
}
"Luna"
is a non-empty string, so Javascript converts it totrue
.The message prints:
Hello, Luna!
Real-Life Use Case: Input Validation
Truthy/falsy checks excel in everyday tasks, such as form validation.
Suppose we want to verify that a user actually entered a name:
let username = "";
if (!username) {
console.log("Please enter your name.");
}
username
is""
, an empty string — falsy.!username
flips falsy totrue
, so the message prints:"Please enter your name."
Why this is useful: Instead of writing if (username === ""
), we rely on Javascript's built-in truthiness to handle all "empty" cases.
Gotchas with Truthy/Falsy
Empty arrays and objects are truthy
if ([]) console.log("Runs, because [] is truthy!");
if ({}) console.log("Runs, because {} is truthy!");
Even though they contain "nothing," arrays and objects are always truthy because they're still real, allocated values.
Loose equality and accidental coercion
console.log("0" == false); // true 😬
Here, Javascript converts both sides before comparing:
"0"
→0
→false
.This is why we almost always prefer
===
, which avoids these conversions.
Why Understanding Truthy/Falsy Matters
Beginners often get tripped up when Javascript silently converts values. Knowing these rules helps us:
Write reliable conditions (
if
,while
, etc.)Avoid bugs caused by unexpected type coercion
Quickly check if a variable has "something meaningful" in it
Quick tip: Be explicit when needed. Instead of relying on truthiness, check precisely what you want:
if (username.length === 0) {
console.log("Username is empty.");
}
This avoids surprises from values like []
, {}
, or "0"
.
Non-Boolean Returns — Why Logical Operators Don't Always Give true or false
We usually think of logical operators (&&
, ||
) as tools that return a true
or false
answer, but in Javascript, that's not always the case. Instead of strictly returning true
or false
, they often give us the actual value of one of the operands.
Here's what's happening:
&&
(AND) returns the first falsy value it finds. If none are falsy, it returns the last value.||
(OR) returns the first truthy value it finds. If none are truthy, it returns the last value.
Alright, let's melt that brain freeze with an example ❄️➡️🔥
console.log("Luna" && "Marco"); // "Marco"
console.log("Luna" || "Marco"); // "Luna"
Why? Both "Luna"
and "Marco"
are truthy (not empty, not false
, not zero). &&
goes all the way through and returns the last value, "Marco"
. Similarly ||
returns the first truthy value, "Luna"
Another example:
console.log("" || "Default"); // "Default"
The first value ""
is falsy (empty string), so ||
skips it and returns the first truthy value, "Default".
This behaviour is why we often see logical operators used for default values:
let username = userInput || "Anonymous";
console.log(username); // If userInput is empty, use "Anonymous"
Or for safe function calls:
user && sendEmail(user); // sendEmail runs only if user exists (is truthy)
Why does this matter?
It's convenient, but it can also lead to unexpected surprises. For example:
console.log(0 || 42); // 42 — but 0 might be a valid value!
Here, 0
is falsy, so ||
ignores it and gives us 42
, even though we might have wanted to keep 0
.
Takeaway: Logical operators return one of their original values, not always true
or false
. Knowing this helps us write cleaner code and avoid unexpected "magic" values.
Equality in Javascript: == vs ===
Equality checks are one of Javascript's most famous "gotchas" — the places where beginners get tripped up most often. Two operators look almost the same — ==
and ===
— but they behave very differently. Let's break it down step by step.
The Loose Equality Operator: ==
The loose equality operator ==
checks if two values are "equal" — but it allows type coercion.
That means before comparing, Javascript tries to convert both values to the same type.
console.log("5" == 5); // true 😬
"5"
is a string, and5
is a number.==
converts the string"5"
into the number5
, then compares5 == 5
, which istrue
.
console.log(false == 0); // true
false
becomes0
when coerced to a number.Now it's
0 == 0
, which istrue
.
console.log("" == false); // true
""
(empty string) becomes0
, andfalse
also becomes0
.So,
0 == 0
→ true.
The problem?
==
tries too hard to find equality, often resulting in surprising matches.
It's like comparing apples to boxes of apples — Javascript opens the box and says, "Well, if I squint, they're the same!"
The Strict Equality Operator: ===
The strict equality operator ===
is much more stringent. It does not allow type coercion.
For two values to be strictly equal:
They must have the same value.
They must have the same type.
The strict equality operator ===
first checks if both values have the same type. If the types don't match, it immediately returns false
. If the types do match, it then checks whether the values themselves are the same. Only when both type and value match does it return true
.
Examples:
console.log("5" === 5); // false
"5"
is a string,5
is a number.Types are different, so
===
immediately returnsfalse
.
console.log(5 === 5); // true
Both are numbers, and both have the value
5
.So
===
returns true.
When Should We Use Which?
Use
===
by default. It's predictable, avoids type coercion, and saves us from weird bugs.Use
==
only when we intentionally want type conversion — which is very rare in modern Javascript.
Think of it like this:
==
says, "If I do a little mental gymnastics, these could be the same."===
says, "No squinting — they must match exactly, both in type and value."
Edge Cases: NaN
and Object.is
()
Here's a fun (and confusing!) fact:
console.log(NaN === NaN); // false
NaN
(Not-a-Number) is the only value in Javascript that is not equal to itself.Why? Because by definition, "not a number" can't equal any number — not even itself.
How do we check for NaN
?
console.log(Number.isNaN(NaN)); // true
console.log(Object.is(NaN, NaN)); // true
Number.isNaN()
andObject.is
(
) correctly tell us if a value isNaN
.
Why Does This Matter?
Using ==
can lead to bugs that are difficult to spot, as type coercion occurs behind the scenes.
console.log(0 == ""); // true 😬
console.log(false == "0"); // true 🤯
We might expect these to be false
, but ==
converts both sides to numbers, then compares.
By sticking to ===
, we make our comparisons crystal clear — no hidden conversions, no surprises.
Takeaway
Always prefer
===
and!==
— they're safer and more predictable.Use
==
only when you fully understand and want its coercion behaviour.Remember: Type coercion is one of Javascript's most common beginner traps.
Putting It All Together
Let's see a practical example where we combine everything we've learned — truthy/falsy checks, number validation, type conversion, and conditional logic:
let userInput = prompt("Enter your age:");
if (userInput && !isNaN(userInput)) {
let age = Number(userInput); // convert the string to a number
if (age >= 18) {
console.log("Access granted!");
} else {
console.log("Sorry, you must be 18 or older.");
}
} else {
console.log("Please enter a valid number.");
}
What's happening here?
We check if
userInput
is truthy:prompt()
always returns a string. If the user leaves it blank, it's an empty string""
, which is falsy.We ensure the input is a number:
isNaN(userInput)
tries to convert the input to a number and checks if it's "Not a Number." We use!isNaN(userInput)
to confirm that it's a numeric value.We convert the input to a number:
Number(userInput)
converts the input string into a numerical value for comparison.We make a decision:
If
age >= 18
, we grant access.Otherwise, we inform the user that they must be at least 18 years old.
Invalid input? We ask them to enter a valid number.
This example shows how truthy/falsy checks, proper type handling, and conditionals work together to make our programs reliable and user-friendly.
Key Takeaways
Booleans are the foundation of all decision-making in Javascript.
Conditions let our programs react dynamically — doing the right thing at the right time.
Truthy and falsy values decide whether a block runs or not.
Use
===
for equality checks to avoid surprising type coercion.Always validate user input — never trust raw data.
What's Next?
Now that we've got a handle on control flow, loops, and operators, it's time to dive into one of the most crucial and exciting parts of Javascript — functions. They're the building blocks of all reusable and modular code.
Stay tuned — we're just getting started! 🚀
Subscribe to my newsletter
Read articles from Sangy K directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sangy K
Sangy K
An Introvert Coder | Trying to be a Full-stack Developer | A Wannabe Content Creator