1. Learning Objective
Until now, your JavaScript code has executed strictly from top to bottom, running every single line in order. Real software doesn't work like that! Real software makes decisions based on data.
In this lesson, you will learn how to control the flow of execution using conditionals and logic:
- Understand Control Flow and how JavaScript decides which code runs and which code gets skipped.
- Master Comparison Operators (
===,!==,>,<,>=,<=) and understand why loose equality (==) is dangerous. - Use
if,else if, andelseblocks to branch execution. - Master the exact list of 8 Falsy values in JavaScript and understand Truthy evaluation.
- Combine conditions with Logical Operators (
&&,||,!) and leverage Short-Circuit Evaluation. - Use the Nullish Coalescing Operator (
??) vs the OR operator (||) for safe default values. - Write concise inline decisions using the Ternary Operator (
? :). - Handle multi-case branching using
switchstatements and know when to use them overif/else.
💡 Why this matters in real-world development
Every dynamic web application is built on conditionals:
- Auth Guards:
if (!user.isLoggedIn) { redirectToLogin(); } - E-Commerce Checkout:
if (cartTotal > 50) { applyFreeShipping(); } - UI Rendering in React:
{isLoading ? <Spinner /> : <ProductList />} - Form Validation:
if (email.includes("@")) { submitForm(); } else { showError(); }
2. Prerequisites Revision
Before diving in, let's quickly review the core concepts from previous lessons that conditionals build upon:
| Concept | What It Means | Example |
|---|---|---|
| Variables | Containers that store values in memory. | const userAge = 20; |
| Boolean Type | A primitive data type with only two values: true or false. |
const isOver18 = true; |
| Functions | Reusable blocks of code that take inputs and return outputs. | function checkAge(age) { ... } |
| Events | User interactions like clicks or input changes that trigger code. | button.addEventListener("click", handleClick); |
3. Concept Explanation (From Scratch)
What is "Control Flow"?
By default, JavaScript reads and executes your script line by line from top to bottom. This sequential execution is called default control flow. Conditionals are special structures that interrupt this straight-line path, allowing your program to take different branches based on whether a condition is true or false.
1. Comparison Operators
Before making a decision, JavaScript needs to compare values. A comparison expression always evaluates to a Boolean: true or false.
| Operator | Name | Example | Result | Why / Notes |
|---|---|---|---|---|
=== |
Strict Equality | 5 === 55 === "5" |
truefalse |
Checks both value AND data type. Always use this! |
!== |
Strict Inequality | 10 !== 55 !== "5" |
truetrue |
Returns true if value OR data type is different. |
> |
Greater Than | 10 > 5 |
true |
Is left value strictly larger than right value? |
< |
Less Than | 3 < 8 |
true |
Is left value strictly smaller than right value? |
>= |
Greater Than or Equal | 18 >= 18 |
true |
Is left value larger than or equal to right value? |
<= |
Less Than or Equal | 5 <= 10 |
true |
Is left value smaller than or equal to right value? |
== |
Loose Equality ⚠️ | 5 == "5" |
true |
DANGER! Converts types automatically before comparing. Avoid in production! |
2. The if, else if, and else Decision Ladder
The basic structure for decision-making in JavaScript:
if (condition) {
// Runs if condition is true
} else if (anotherCondition) {
// Runs if first condition was false AND anotherCondition is true
} else {
// Runs if all previous conditions were false
}
3. Truthy and Falsy Values
In JavaScript, every single value has an inherent boolean equivalent when converted to a boolean (a process called coercion).
❌ The EXACT 8 Falsy Values in JavaScript
Only these 8 values evaluate to false in a boolean context:
false (the boolean false)0 (number zero)-0 (negative zero)0n (BigInt zero)"" (empty string)null (absence of value)undefined (unassigned)NaN (Not-a-Number)✅ Truthy Values
EVERYTHING ELSE in JavaScript is Truthy! This includes:
42, -1, 3.14)"hello", "0", "false")[] (Yes! An empty array is truthy!){} (Yes! An empty object is truthy!)function() {}4. Logical Operators: &&, ||, !
Logical operators let you combine multiple conditions together:
&&(AND): ReturnstrueONLY if ALL conditions are true.||(OR): Returnstrueif AT LEAST ONE condition is true.!(NOT): Flips boolean value.!truebecomesfalse. Double bang!!valconverts any value to its actual boolean representation!
5. Short-Circuit Evaluation
JavaScript evaluates logical expressions from left to right and stops as soon as the outcome is guaranteed:
- In
A && B: IfAis falsy, JS stops immediately and returnsA. It never evaluatesB! - In
A || B: IfAis truthy, JS stops immediately and returnsA. It never evaluatesB!
6. Nullish Coalescing Operator (??)
Introduced in ES2020, ?? returns the right side ONLY if the left side is null or undefined. Unlike ||, it does NOT treat 0 or "" as missing!
const userScore = 0;
// Problem with OR (||): treats 0 as falsy and overwrites valid score 0!
const score1 = userScore || 10; // score1 is 10 (Wrong!)
// Solution with Nullish Coalescing (??): keeps 0!
const score2 = userScore ?? 10; // score2 is 0 (Correct!)
7. Ternary Operator (? :)
A shorthand inline replacement for a simple if/else block that returns a value:
// Syntax: condition ? valueIfTrue : valueIfFalse
const status = age >= 18 ? "Adult" : "Minor";
8. The switch Statement
When you have a single variable that could match many exact discrete values (e.g. user role, order status, days of the week), switch provides clean syntax:
switch (orderStatus) {
case "pending":
console.log("Order placed.");
break;
case "shipped":
console.log("Order on the way.");
break;
case "delivered":
console.log("Order complete.");
break;
default:
console.log("Unknown status.");
}
4. Mental Model & Analogies
🎢 Real-World Analogy: Theme Park Security Gate
Imagine you are entering a high-speed roller coaster ride at a theme park:
- Comparison (
height >= 140): The security height stick measure. You are either tall enough (true) or not (false). - Logical AND (
height >= 140 && hasTicket): You MUST be tall enough AND have a valid ticket. If you fail height, the guard doesn't even bother checking your ticket (Short-Circuit evaluation!). - Logical OR (
isVIP || hasFastPass): You get priority entry if you are either a VIP guest OR holding a fast pass. If you show a VIP card, the guard stops checking fast pass immediately! - Switch Statement: A multi-lane ticket gate (Lane 1: Standard, Lane 2: VIP, Lane 3: Staff). Depending on your ticket type, you walk directly into your assigned lane.
5. Visual Flowcharts & Tables
if / else decision branch in JavaScript memory.Comparison: Loose Equality (==) vs Strict Equality (===)
| Expression | Loose Equality == |
Strict Equality === |
Why the difference occurs |
|---|---|---|---|
5 == "5" |
true | false | == coerces string "5" to number 5. === sees Number vs String. |
0 == false |
true | false | == coerces boolean false to number 0. |
"" == false |
true | false | == coerces empty string to number 0 and false to 0. |
null == undefined |
true | false | Spec rule ECMA-262 7.2.14: null and undefined loosely equal only each other. |
6. Code Examples: Basic to Industry Level
Example 1: Basic if / else if / else
function calculateDiscount(cartTotal) {
// Line 1: Check if total qualifies for top-tier 20% discount
if (cartTotal >= 100) {
return cartTotal * 0.20;
}
// Line 2: Check if total qualifies for mid-tier 10% discount
else if (cartTotal >= 50) {
return cartTotal * 0.10;
}
// Line 3: Fallback for purchases below $50
else {
return 0;
}
}
console.log(calculateDiscount(120)); // Output: 24 (20%)
console.log(calculateDiscount(75)); // Output: 7.5 (10%)
console.log(calculateDiscount(30)); // Output: 0
Example 2: Modern Early Return Pattern (Guard Clauses)
Instead of deeply nested if/else blocks, professional software engineers write clean Guard Clauses:
function processUserPayment(user, amount) {
// Guard Clause 1: Validate input existence
if (!user) {
return { success: false, reason: "No user provided" };
}
// Guard Clause 2: Check active status
if (!user.isActive) {
return { success: false, reason: "Account inactive" };
}
// Guard Clause 3: Verify funds
if (user.balance < amount) {
return { success: false, reason: "Insufficient balance" };
}
// Main Happy Path (un-nested!)
user.balance -= amount;
return { success: true, newBalance: user.balance };
}
7. Visual Execution & JS Engine Mechanics
⚙️ What Happens Inside the V8 Engine During if (a && b)
- Step 1 (Parse Expression): The engine creates an Execution Context and evaluates identifier
ain the current Environment Record (Scope). - Step 2 (ToBoolean Abstract Operation): V8 invokes ECMAScript internal spec operation
ToBoolean(a). - Step 3 (Short-Circuit Check):
- If
ToBoolean(a)returnsfalse, V8 halts evaluation of the line immediately!bis never read or executed. The expression returnsa. - If
ToBoolean(a)returnstrue, V8 evaluates identifierband returnsb.
- If
- Step 4 (Branch Jump): The Bytecode Compiler issues a conditional jump instruction (
JumpIfFalse) to skip theifblock body if the result was falsy.
8. Common Mistakes & How to Fix Them
❌ Mistake 1: Accidental Assignment in Condition (= instead of ===)
// WRONG: Assigns 5 to x, which evaluates to 5 (truthy!), so block ALWAYS runs!
let x = 0;
if (x = 5) {
console.log("x is 5!"); // Always executes!
}
// CORRECT: Use strict equality comparison
if (x === 5) {
console.log("x is 5!");
}
❌ Mistake 2: Using || for Defaults when Zero or Empty String is Valid
// WRONG: If user set custom padding to 0, 0 is falsy, so it resets to 20!
const userPadding = 0;
const padding = userPadding || 20; // padding becomes 20!
// CORRECT: Use Nullish Coalescing (??) which respects 0 and ""
const safePadding = userPadding ?? 20; // safePadding is 0!
❌ Mistake 3: Forgetting break in Switch Statements (Fall-Through Bug)
// WRONG: Missing break causes execution to fall through to next case!
switch (role) {
case "admin":
enableAdminTools();
// Missing break!
case "user":
enableUserTools(); // Admin gets this too accidentally!
break;
}
9. Interview Perspective & Tricky Questions
🔥 Top Interview Questions & Coding Traps
Q1: What does [] == ![] evaluate to and WHY?
Answer: It evaluates to true! Here is the step-by-step ECMAScript coercion sequence:
![]is evaluated first.[]is an object, which is truthy. So![]becomesfalse.- Expression is now
[] == false. - Spec rule: Comparing Object to Boolean coerces boolean to number.
falsebecomes0. Expression:[] == 0. - Spec rule: Comparing Object to Number invokes
ToPrimitive([]), which yields empty string"". Expression:"" == 0. - Spec rule: Comparing String to Number coerces
""to number0. Expression:0 == 0. - Result:
true! (This is why strict===is mandatory in modern software engineering).
Q2: What is the difference between || and ???
Answer: || checks for falsy values (8 values including 0, "", false). ?? checks strictly for nullish values (only null and undefined).
10. Industry Best Practices
- Rule 1: Always use
===and!==. Never use loose==unless explicitly checking for bothnullandundefinedviaval == null. - Rule 2: Prefer Guard Clauses over Nested
if/else. Keep code flat and easy to read. - Rule 3: Use
??for Default Fallbacks. Protect user options where0or""are valid choices. - Rule 4: Keep Boolean expressions readable. Extract complex conditions into well-named boolean variables:
// Hard to read: if (user.age >= 18 && user.hasActiveSubscription && !user.isBanned) { ... } // Clean & Self-Documenting: const canAccessPremiumContent = user.age >= 18 && user.hasActiveSubscription && !user.isBanned; if (canAccessPremiumContent) { ... }
11. Real-World Use Cases in Modern Stacks
1. React & Next.js Conditional Rendering
// In React JSX: Short-circuiting with &&
function DashboardHeader({ user }) {
return (
<header>
<h1>Welcome back, {user.name}</h1>
{/* Renders badge ONLY if user is admin */}
{user.isAdmin && <span className="admin-badge">Admin</span>}
{/* Ternary for state-based UI */}
{user.isPro ? <ProFeatures /> : <UpgradeBanner />}
</header>
);
}
2. Node.js & Express Authentication Middleware
// Express API route auth guard
function requireAuth(req, res, next) {
const authHeader = req.headers.authorization;
// Guard Clause: missing token
if (!authHeader) {
return res.status(401).json({ error: "Access denied. No token provided." });
}
// Guard Clause: invalid token syntax
if (!authHeader.startsWith("Bearer ")) {
return res.status(400).json({ error: "Invalid token format." });
}
next(); // Token OK -> proceed to controller
}
Interactive JS Playground: Test Conditionals Live
12. Practice Questions & Exercises
Test your knowledge with these 10 practice questions (Answers at the end of the session!):
- What is the boolean evaluation of
Boolean("0")? - What does
5 > 3 && 2 < 1evaluate to? - What is the difference between
5 == "5"and5 === "5"? - What are the 8 falsy values in JavaScript?
- What will
const x = null ?? "default";store inx? - What will
const y = "" || "fallback";store iny? - Convert this
if/elsestatement into a ternary expression:let msg; if (score >= 50) msg = "Pass"; else msg = "Fail"; - Why does
if ([]) console.log("Hi");print "Hi"? - What happens if you omit the
breakstatement inside aswitchcase? - What does
!trueevaluate to? What about!!100?
13. Mini Project: Interactive E-Commerce Discount & Eligibility Calculator
Use the live interactive tool below to test how real-world nested decision rules calculate customer totals:
🛍️ Smart Discount Engine
Interactive Self-Assessment
Concept Quiz
Fill-in-the-Blank Retrieval Practice
14. Lesson Summary
- Conditionals control the branch path of execution based on boolean truth values.
- Always use strict equality
===and strict inequality!==. - Memorize the 8 Falsy values:
false,0,-0,0n,"",null,undefined,NaN. Everything else is truthy (including[]and{}!). - Use Guard Clauses to keep functions clean and avoid nested
if/elsecallback hell. - Use
??when0or""are valid user inputs that shouldn't be overwritten by fallbacks.
15. Quick 5-Minute Revision Notes
===checks Value + Type.==coerces types (Avoid!).A && Breturns A if A is falsy, else returns B.A || Breturns A if A is truthy, else returns B.A ?? Breturns A if A is NOT null/undefined, else returns B.cond ? x : yis shorthand for inlineif/else.
16. Cumulative Challenge
🏆 Challenge: Building an Automated Grade & Scholarship Evaluator
Combine Lesson 9 (Variables), Lesson 10 (Functions & Events), and Lesson 11 (Conditionals) to build a function evaluateStudent(score, attendance, hasDisciplinaryAction):
- If
hasDisciplinaryActionis true, return"Disqualified due to conduct"immediately (Guard clause!). - If attendance is less than 75%, return
"Failed due to low attendance". - If score is >= 90 AND attendance >= 90, return
"Passed with High Honors & Scholarship". - If score is >= 70, return
"Passed". - Else, return
"Failed".