How your code makes decisions — and how you can tell it exactly what to do.
Here's something that blew my mind when I first started learning JavaScript: code doesn't just run top to bottom and call it a day. It can think. Well, not actually think — but it can make decisions based on conditions. "Is the user logged in? Show the dashboard. Not logged in? Show the login page."
That decision-making ability is called control flow, and it's what separates a static script from an actual, useful program. In the ChaiCode Web Dev Cohort 2026, this was the moment JavaScript stopped feeling like a calculator and started feeling like a real programming language.
Let's break it all down.
What Is Control Flow?
In everyday life, you make decisions constantly:
- "If it's raining, I'll take an umbrella. Otherwise, I'll leave it at home."
- "If my marks are above 90, I'll celebrate. If they're above 60, I'll be satisfied. Otherwise, I need to study harder."
- "Based on the day of the week, I'll decide what to cook."
Control flow is exactly this — but in code. It's the order in which JavaScript executes statements, and more importantly, how it decides which statements to execute based on certain conditions.
Without control flow, your code would be a straight line — every line runs, every time, no exceptions. That's boring and pretty useless. Control flow gives your program the ability to branch, skip, and choose.
Start
↓
Is the condition true?
├── YES → Do this thing
└── NO → Do that thing instead
↓
Continue with the rest of the code
That's the core idea. Now let's look at the tools JavaScript gives us.
The if Statement — The Simplest Decision
The if statement is the most basic building block of control flow. It says: "If this condition is true, run this code."
Syntax
if (condition) {
// Code that runs ONLY if condition is true
}
Example
let age = 22;
if (age >= 18) {
console.log("You are an adult. 🎉");
}
// Output: "You are an adult. 🎉"
That's it. JavaScript checks the condition inside the parentheses. If it evaluates to true, the code inside the curly braces runs. If it's false, JavaScript skips it entirely and moves on.
Another Example
let temperature = 40;
if (temperature > 35) {
console.log("It's really hot outside! Stay hydrated. 🥤");
}
// Output: "It's really hot outside! Stay hydrated. 🥤"
But what happens if the condition is false? Right now — nothing. The code just silently skips. That's where else comes in.
The if-else Statement — Handling Both Outcomes
Most decisions aren't just "do this if true." They're "do this if true, otherwise do that." The if-else statement handles both paths.
Syntax
if (condition) {
// Runs if condition is true
} else {
// Runs if condition is false
}
Example
let marks = 45;
if (marks >= 50) {
console.log("You passed! ✅");
} else {
console.log("You failed. Try again. ❌");
}
// Output: "You failed. Try again. ❌"
How It Works, Step by Step
Let me walk you through exactly what JavaScript does here:
- JavaScript looks at
marks >= 50. Is45 >= 50? No — that'sfalse. - Since the condition is
false, JavaScript skips theifblock entirely. - JavaScript enters the
elseblock and runsconsole.log("You failed. Try again. ❌"). - Done. Moves on to the next line after the whole
if-else.
Flowchart: If-Else Decision Making
┌──────────────┐
│ START │
└──────┬───────┘
↓
┌────────────────────┐
│ Is marks >= 50? │
└────────┬───────────┘
│
┌───────┴───────┐
│ │
YES ↓ NO ↓
┌────────────┐ ┌──────────────┐
│ "You │ │ "You failed. │
│ passed!" │ │ Try again." │
└─────┬──────┘ └──────┬───────┘
│ │
└───────┬────────┘
↓
┌──────────────┐
│ END │
└──────────────┘
One condition, two possible paths. Simple and clean.
The else if Ladder — Multiple Conditions
Real life rarely has just two outcomes. "Did you pass or fail?" is simple. But what about grading? You need A, B, C, D, and F. That's where else if comes in.
Syntax
if (condition1) {
// Runs if condition1 is true
} else if (condition2) {
// Runs if condition1 is false AND condition2 is true
} else if (condition3) {
// Runs if condition1 and condition2 are false AND condition3 is true
} else {
// Runs if ALL conditions above are false
}
Example: Grade Calculator
let score = 78;
if (score >= 90) {
console.log("Grade: A 🌟");
} else if (score >= 80) {
console.log("Grade: B 👍");
} else if (score >= 70) {
console.log("Grade: C ✅");
} else if (score >= 60) {
console.log("Grade: D 😐");
} else {
console.log("Grade: F ❌");
}
// Output: "Grade: C ✅"
Step-by-Step Breakdown
- Is
78 >= 90? No. Skip. - Is
78 >= 80? No. Skip. - Is
78 >= 70? Yes! Run this block →"Grade: C ✅". - JavaScript stops here. It does NOT check the remaining conditions.
That last point is important: once a condition is true, JavaScript runs that block and skips everything below it. It doesn't keep checking. This makes else if efficient — order your conditions from most specific to least specific.
Another Example: Time-Based Greeting
let hour = 15; // 3:00 PM (24-hour format)
if (hour < 12) {
console.log("Good morning! ☀️");
} else if (hour < 17) {
console.log("Good afternoon! 🌤️");
} else if (hour < 21) {
console.log("Good evening! 🌇");
} else {
console.log("Good night! 🌙");
}
// Output: "Good afternoon! 🌤️"
The switch Statement — Clean Multi-Way Branching
Sometimes you're checking one variable against a bunch of specific values. You could use a long else if chain, but it gets ugly fast. That's when switch steps in.
Syntax
switch (expression) {
case value1:
// Code for value1
break;
case value2:
// Code for value2
break;
case value3:
// Code for value3
break;
default:
// Code if no case matched
}
Example: Day of the Week
let day = 3;
switch (day) {
case 1:
console.log("Monday");
break;
case 2:
console.log("Tuesday");
break;
case 3:
console.log("Wednesday");
break;
case 4:
console.log("Thursday");
break;
case 5:
console.log("Friday");
break;
case 6:
console.log("Saturday 🎉");
break;
case 7:
console.log("Sunday 🎉");
break;
default:
console.log("Invalid day number!");
}
// Output: "Wednesday"
Switch-Case Branching Diagram
┌──────────────┐
│ day = 3 │
└──────┬───────┘
↓
┌───── case 1? ─── NO ──┐
│ YES │
"Monday" ┌───── case 2? ─── NO ──┐
│ YES │
"Tuesday" ┌───── case 3? ─── NO ──┐
│ YES │
"Wednesday" ✅ (keeps checking...)
+ break; │
┌─────┘
↓
default:
"Invalid day!"
The break Keyword — Why It Matters
This is crucial and I want to be very clear about it: if you forget break, JavaScript will keep running the next cases even after it finds a match. This is called "fall-through" and it's almost always a bug.
let fruit = "apple";
// ❌ WITHOUT break — watch what happens
switch (fruit) {
case "apple":
console.log("You picked apple");
case "banana":
console.log("You picked banana");
case "mango":
console.log("You picked mango");
}
// Output:
// "You picked apple"
// "You picked banana" ← Wait, what?!
// "You picked mango" ← This too?!
JavaScript matched "apple", but without break, it just keeps falling through every case below it. Now let's fix it:
// ✅ WITH break — correct behavior
switch (fruit) {
case "apple":
console.log("You picked apple");
break;
case "banana":
console.log("You picked banana");
break;
case "mango":
console.log("You picked mango");
break;
}
// Output: "You picked apple" — only this one, as expected
Rule of thumb: Always include break at the end of each case unless you specifically intend fall-through behavior (which is rare and should be commented when intentional).
The default Case
default is like the else in an if-else chain. It runs when no case matches. It's optional, but I always include it as a safety net.
let color = "purple";
switch (color) {
case "red":
console.log("🔴");
break;
case "green":
console.log("🟢");
break;
case "blue":
console.log("🔵");
break;
default:
console.log("Unknown color 🤷");
}
// Output: "Unknown color 🤷"
When to Use switch vs if-else
This is a question I had early on, and honestly, the answer is simpler than I expected:
| Situation | Use This |
|---|---|
Checking ranges (> 50, <= 100) |
if-else |
| Checking one variable against exact values | switch |
Complex conditions with && or `\ |
\ |
| Many exact matches (days, months, roles) | {% raw %}switch
|
| 2-3 simple conditions | if-else |
Example Where if-else Is Better
// Checking a RANGE — switch can't do this cleanly
let score = 85;
if (score >= 90) {
console.log("Excellent");
} else if (score >= 70) {
console.log("Good");
} else {
console.log("Needs improvement");
}
Example Where switch Is Better
// Checking EXACT VALUES — switch is cleaner
let role = "admin";
switch (role) {
case "admin":
console.log("Full access");
break;
case "editor":
console.log("Can edit content");
break;
case "viewer":
console.log("Read-only access");
break;
default:
console.log("Unknown role");
}
Both work. But using the right one for the right situation makes your code cleaner and easier to read. When I'm dealing with exact values like days, months, or user roles — I reach for switch. For everything else, if-else is my go-to.
Let's Practice: Hands-On Assignments
Assignment 1: Positive, Negative, or Zero
Write a program that checks whether a number is positive, negative, or zero.
let number = -7;
if (number > 0) {
console.log(number + " is positive ✅");
} else if (number < 0) {
console.log(number + " is negative ❌");
} else {
console.log("The number is zero 🔄");
}
// Output: "-7 is negative ❌"
Why if-else? Because we're checking ranges (greater than, less than, equal to zero). switch can't handle range comparisons cleanly — it's designed for exact value matching. So if-else is the natural choice here.
Assignment 2: Day of the Week Using switch
let dayNumber = 5;
switch (dayNumber) {
case 1:
console.log("Monday 📅");
break;
case 2:
console.log("Tuesday 📅");
break;
case 3:
console.log("Wednesday 📅");
break;
case 4:
console.log("Thursday 📅");
break;
case 5:
console.log("Friday 🎉");
break;
case 6:
console.log("Saturday 🥳");
break;
case 7:
console.log("Sunday 😴");
break;
default:
console.log("Invalid day! Enter a number between 1 and 7.");
}
// Output: "Friday 🎉"
Why switch? Because we're matching one variable (dayNumber) against seven specific, exact values. An if-else chain would work, but switch is cleaner and more readable when you have this many exact-match cases. Each case maps directly to one outcome — that's exactly what switch is built for.
Bonus: Try These Yourself
- Change
numberto0and15and see how the output changes. - Change
dayNumberto8and see thedefaultcase kick in. - Remove a
breakfrom one of the switch cases and observe the fall-through behavior.
Key Takeaways
- Control flow lets your code make decisions instead of blindly running every line. It's what makes programs smart.
-
ifruns code when a condition istrue. Addelseto handle thefalsepath. Chainelse iffor multiple conditions. -
switchis your friend when you're matching one value against many exact possibilities. Always usebreakto prevent fall-through. - Use
if-elsefor ranges and complex conditions. Useswitchfor exact-value matching. - The
defaultcase inswitchis likeelse— it catches anything that didn't match. Always include it.
Wrapping Up
Control flow is where your JavaScript code starts actually doing something interesting. Before this, everything was just storing values and doing math. Now your programs can make decisions, react to different inputs, and handle multiple scenarios.
I'm learning these concepts through the ChaiCode Web Dev Cohort 2026 under Hitesh Chaudhary and Piyush Garg, and I'll be honest — control flow was the first time JavaScript felt genuinely powerful to me. Once you understand if-else and switch, you start seeing them everywhere. Form validation? if-else. Navigation menus? switch. User permissions? Both.
If this article helped you, connect with me on LinkedIn or visit PrathamDEV.in. More articles coming as I dive deeper into loops, functions, and beyond.
Happy coding! 🚀
Written by Pratham Bhardwaj | Web Dev Cohort 2026, ChaiCode
Top comments (0)