Learn how to control what your program does next using
if, else if, else, and
switch — the building blocks of every branching decision in
JavaScript.
Decision statements in JavaScript control the flow of
execution based on conditions. They allow a program to choose different paths
depending on whether a condition evaluates to true or
false.
Without decision statements every program would run the same way every time — decision statements are what give code the ability to respond differently to different data, user input, or state.
Think of decision statements like choices you make in real life:
true
if/else if
let marks = 75;
if (marks >= 90) {
console.log("Grade A");
} else if (marks >= 75) {
console.log("Grade B");
} else if (marks >= 60) {
console.log("Grade C");
} else {
console.log("Fail");
}
// Try changing marks to 95, 65, or 40
else if and else branches are skippedelse is optional — it acts as the default if no condition matchedlet 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;
default:
console.log("Weekend");
}
switch compares one expression against multiple exact values using strict equalitybreak exits the switch — without it, execution falls through to the next casedefault runs when no case matches — equivalent to elselet age = 20;
// Long form
let message1;
if (age >= 18) {
message1 = "Adult";
} else {
message1 = "Minor";
}
// Short form — ternary
let message2 = age >= 18 ? "Adult" : "Minor";
console.log(message1); // Adult
console.log(message2); // Adult — same result, one line
condition ? valueIfTrue : valueIfFalseif/elselet signal = "red";
switch (signal) {
case "red":
console.log("Stop");
break;
case "yellow":
console.log("Ready");
break;
case "green":
console.log("Go");
break;
default:
console.log("Invalid signal");
}
// Intentional fall-through — shared behaviour for multiple cases
let month = 4; // April
switch (month) {
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
console.log("31 days");
break;
case 4: case 6: case 9: case 11:
console.log("30 days");
break;
case 2:
console.log("28 or 29 days");
break;
}
break — intentional fall-throughbreakTwo everyday systems that use decision logic constantly:
Click ▶ Preview, enter a score, and watch an
if / else if / else chain assign the correct grade live.
<!DOCTYPE html>
<html>
<head><title>Decision Demo</title></head>
<body style="font-family:sans-serif;padding:24px;background:#f8f9fa">
<h2>Check Result</h2>
<input id="scoreInput" type="number" placeholder="Enter score (0–100)"
style="padding:8px 12px;border:1px solid #ccc;border-radius:6px;
font-size:1rem;width:210px">
<button onclick="checkGrade()"
style="margin-left:8px;padding:8px 18px;background:#f7df1e;border:none;
border-radius:6px;cursor:pointer;font-weight:700;font-size:1rem">
Check Grade
</button>
<div id="output" style="margin-top:16px;font-size:1.05rem;line-height:2"></div>
<script>
function checkGrade() {
let score = Number(document.getElementById("scoreInput").value);
let out = document.getElementById("output");
if (isNaN(score) || score < 0 || score > 100) {
out.innerHTML = "<b style='color:red'>Enter a valid score between 0 and 100.</b>";
return;
}
let grade, color;
if (score >= 90) { grade = "A — Excellent"; color = "#22c55e"; }
else if (score >= 75) { grade = "B — Good"; color = "#3b82f6"; }
else if (score >= 60) { grade = "C — Average"; color = "#f59e0b"; }
else if (score >= 40) { grade = "D — Below Average"; color = "#f97316"; }
else { grade = "F — Fail"; color = "#ef4444"; }
out.innerHTML =
"<b>Score:</b> " + score + "<br>" +
"<b>Grade:</b> <b style='color:" + color + ";font-size:1.15rem'>" + grade + "</b>";
}
</script>
</body>
</html>
let num = 7;
// Use if/else to print "Even" or "Odd"
num % 2 === 0 as the condition — if true it's even, else it's oddnum to 12 and verify it prints "Even"let fruit = "apple";
// Write a switch with cases for apple, banana, mango
"apple" → "Red fruit", "banana" → "Yellow fruit", "mango" → "King of fruits"default case: "Unknown fruit"break in each caselet x = 5;
if (x > 10) {
console.log("A");
} else {
console.log("B");
}
5 > 10 is false, so the if block is skipped and the else block runs, printing "B".
break is missing from a switch case?
let n = 1;
switch (n) {
case 1:
console.log("One");
case 2:
console.log("Two");
break;
case 3:
console.log("Three");
}
break, JavaScript continues executing the next case even if its value doesn't match — called fall-through. Here case 1 runs, then falls into case 2. Both "One" and "Two" print.
switch is cleaner and more readable when checking one variable against many fixed values. Use if/else if for range conditions (>, <, >=) where switch does not apply.
Choose the right tool: use if/else for range conditions and switch for exact matches:
let score = 82;
// if — best for ranges
if (score >= 90) console.log("A");
else if (score >= 75) console.log("B");
else console.log("C");
// switch — best for exact matches
let lang = "JS";
switch (lang) {
case "JS": console.log("JavaScript"); break;
case "PY": console.log("Python"); break;
default: console.log("Unknown");
}
You can use early return inside functions to avoid deeply nested if blocks — called a "guard clause":
// ✗ Deep nesting — hard to read
function checkAccess(age, hasID) {
if (age >= 18) {
if (hasID) {
console.log("Access granted");
}
}
}
// ✓ Guard clauses — flat and readable
function checkAccessClean(age, hasID) {
if (age < 18) return console.log("Too young");
if (!hasID) return console.log("No ID");
console.log("Access granted");
}
checkAccessClean(20, true);
checkAccessClean(16, true);
Use the ternary operator for simple two-way assignments — but switch back to if/else the moment logic gets complex:
let temp = 35;
// Ternary — clean for one simple choice
let weather = temp > 30 ? "Hot" : "Cool";
console.log(weather);
// Use if/else when the logic needs more branches
let advice;
if (temp > 35) advice = "Stay indoors";
else if (temp > 25) advice = "Light clothing";
else advice = "Wear a jacket";
console.log(advice);
Always add a default to every switch — it catches unexpected values and prevents silent failures:
function getStatus(code) {
switch (code) {
case 200: return "OK";
case 404: return "Not Found";
case 500: return "Server Error";
default: return "Unknown status: " + code; // always provide this
}
}
console.log(getStatus(200));
console.log(getStatus(403)); // caught by default
There is no break after case 2 — predict every line that
will print before running.
let value = 2;
switch (value) {
case 1:
console.log("One");
case 2:
console.log("Two");
case 3:
console.log("Three");
break;
default:
console.log("Default");
}
// value = 2
// case 1: value !== 1 → SKIPPED entirely
// case 2: value === 2 → MATCH — execution begins here
// console.log("Two") → prints "Two"
// No break → FALL THROUGH to next case
// case 3: value !== 3, but we're already inside due to fall-through
// console.log("Three") → prints "Three"
// break → EXIT switch
// default: not reached — we already exited
// Final output:
// Two
// Three
// Key takeaway:
// Without break, execution "falls through" every subsequent
// case regardless of whether the value matches.
// case 1 was skipped because we hadn't entered yet.
// Once inside (at case 2), all remaining cases run until
// a break or the end of the switch is reached.
// Fix: add break after case 2 if fall-through is unintended:
// case 2:
// console.log("Two");
// break; // ← prevents "Three" from printing