Control Flow in JavaScript
What is Control Flow
When you write code, it runs line by line, top to bottom. That is the default. But most real programs cannot work that way — they need to make decisions. Should this user see the dashboard or the login page? Is this score a pass or a fail? Did the user enter a valid age?
Control flow is how you give your program the ability to make those decisions. Instead of always running every line, you control which lines run and which ones get skipped, based on conditions.
Think of it like everyday decisions. If it is raining, you carry an umbrella. Otherwise, you do not. Your brain is running control flow all the time — you just do not call it that.
In code, that looks like this:
if (isRaining) {
carryUmbrella();
} else {
leaveUmbrella();
}
That is the core idea. The rest of this guide is just different ways to express similar decisions.
The if Statement
The if statement is the most basic form of control flow. You give it a condition, and if that condition is true, it runs a block of code. If the condition is false, it skips the block entirely and moves on.
if (condition) {
// runs only when condition is true
}
Real example — checking if someone is old enough to vote:
const age = 20;
if (age >= 18) {
console.log("You can vote.");
}
If age is 20, the condition age >= 18 is true, so the message prints. If age were 15, the condition would be false, nothing prints, and the program moves on.
Step by step what happens here:
JavaScript evaluates
age >= 18That gives either
trueorfalseIf
true, the code inside{}runsIf
false, the block is skipped
The if-else Statement
The if statement alone handles "do something if true." But what if you also want to do something when the condition is false? That is where else comes in.
if (condition) {
// runs when condition is true
} else {
// runs when condition is false
}
Example:
const marks = 45;
if (marks >= 50) {
console.log("Pass");
} else {
console.log("Fail");
}
One of these two paths will always run. There is no in-between. Either the condition is true and you get "Pass", or it is false and you get "Fail".
Step by step:
marks >= 50evaluates tofalse(since 45 is less than 50)The
ifblock is skippedThe
elseblock runsOutput: "Fail"
Flowchart of if-else
[Start]
|
[Check condition]
/ \
true false
| |
[if block] [else block]
\ /
[End]
Only one branch runs. Once it is done, both paths meet again and the program continues.
The else if Ladder
Sometimes there are more than two possible outcomes. Marks are not just pass or fail — you might want grades. Age is not just adult or minor — there might be different categories. The else if ladder lets you check multiple conditions in sequence.
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 none of the above are true
}
Example — grading a student:
const marks = 72;
if (marks >= 90) {
console.log("Grade: A");
} else if (marks >= 75) {
console.log("Grade: B");
} else if (marks >= 60) {
console.log("Grade: C");
} else if (marks >= 40) {
console.log("Grade: D");
} else {
console.log("Grade: F");
}
Output: Grade: C
JavaScript checks each condition from top to bottom. The moment one condition is true, it runs that block and skips everything else. It does not check the remaining conditions.
Step by step for marks = 72:
72 >= 90— false, skip72 >= 75— false, skip72 >= 60— true, run this blockOutput: "Grade: C"
The remaining
else ifandelseare ignored
This "stop at the first true condition" behavior is important. Once a match is found, the rest of the ladder does not matter.
Gotcha — Order Matters
If you flip the conditions carelessly, you get wrong results:
const marks = 95;
if (marks >= 40) {
console.log("Grade: D"); // this runs for 95 too — wrong
} else if (marks >= 90) {
console.log("Grade: A"); // never reached
}
Because 95 >= 40 is true, it stops there and prints "Grade: D" for a student who deserved an A. Always order your conditions from most specific to least specific, or highest to lowest when dealing with ranges.
The switch Statement
The switch statement is designed for a specific situation: when you are checking one variable against multiple exact values.
Instead of writing if x === 1, else if x === 2, else if x === 3... you give switch the variable, and then list out cases for each value you want to handle.
switch (variable) {
case value1:
// runs if variable === value1
break;
case value2:
// runs if variable === value2
break;
default:
// runs if no case matches
}
Example — printing the day of the week:
const 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");
}
Output: Wednesday
JavaScript jumps directly to case 3, runs the code there, hits break, and exits the switch block.
What break Does
break tells JavaScript to stop executing the switch block and move on. Without it, JavaScript keeps running the code in the next case even if that case did not match. This is called fall-through.
const day = 3;
switch (day) {
case 3:
console.log("Wednesday");
// no break here
case 4:
console.log("Thursday");
break;
}
Output:
Wednesday
Thursday
Both lines printed even though day is 3 and not 4. That is fall-through. It is rarely what you want by accident, so always add break unless you have a specific reason not to.
The default Case
default is the fallback. It runs when none of the cases match, similar to the final else in an if-else ladder.
const day = 9;
switch (day) {
case 1:
console.log("Monday");
break;
default:
console.log("Invalid day number");
}
Output: Invalid day number
You do not have to put default at the end — it can go anywhere — but at the end is the convention and makes the most sense to read.
Switch-Case Branching Diagram
[switch(variable)]
|
-----------------------------
| | | |
case 1 case 2 case 3 default
| | | |
[code] [code] [code] [code]
| | | |
[break] [break] [break] |
\ \ \ /
[Continue program]
Each case is a separate branch. break makes sure only one branch runs.
When to Use switch vs if-else
This comes up a lot and there is no single right answer, but here is a practical way to think about it.
Use if-else when:
You are checking ranges (
marks >= 60)The conditions involve different variables
Your conditions involve complex logic (
age > 18 && hasID === true)There are just two or three cases
// ranges — if-else is the right tool
if (temperature > 35) {
console.log("Too hot");
} else if (temperature > 20) {
console.log("Comfortable");
} else {
console.log("Cold");
}
Use switch when:
You are checking one variable against many exact values
The cases are clean and discrete (day numbers, status codes, menu options)
Readability matters and there are many cases to handle
// exact values — switch reads much cleaner here
switch (statusCode) {
case 200:
console.log("OK");
break;
case 404:
console.log("Not Found");
break;
case 500:
console.log("Server Error");
break;
default:
console.log("Unknown status");
}
Writing this as a chain of else if statements would work, but it would be harder to read. Switch is just the cleaner choice for that pattern.
Gotcha — switch Uses Strict Equality
Switch compares values using ===, not ==. This means type matters.
const input = "1"; // this is a string
switch (input) {
case 1:
console.log("Number one");
break;
default:
console.log("No match");
}
Output: No match
The string "1" does not strictly equal the number 1, so the case is skipped. If you are reading user input, it usually comes as a string. Either parse it first with parseInt() or write your cases as strings.



