SECTION 1
Historical Context & Motivation
Every useful program must make decisions. Should the game character jump or duck? Should the shopping cart apply a discount or charge full price? From the very earliest days of computing, programmers needed a way to tell the machine: "If this condition is true, do one thing; otherwise, do something else." This idea — conditional branching — is one of the most fundamental concepts in all of computer science, and it has a surprisingly rich history.
1843 • Ada Lovelace's Notes
1957 • FORTRAN's IF Statement
1972 • C Language & Structured Control Flow
1995 • JavaScript Brings Conditionals to the Web
The core question that if/else chains answer has remained the same for over 180 years: How can a program choose different paths of execution based on data it receives at runtime? Today you will learn to write these decision structures in JavaScript and, just as importantly, to order your conditions so they don't silently produce wrong results.
SECTION 2
Core Principles of If/Else Chains
Before writing any code, you need to understand the building blocks. An if/else chain is a series of condition tests that the JavaScript engine evaluates from top to bottom. The moment one condition evaluates to true, the engine runs that block and skips every remaining branch. If no condition matches, an optional else block serves as the default fallback. The following principles govern how these chains behave.
Top-Down Evaluation
true condition wins, and all later branches are skipped — even if they would also be true.Mutual Exclusivity
else) will execute. This differs from separate if statements, where multiple blocks can run.Condition Order Matters
The else Safety Net
else block catches every case not handled above it. Including one prevents unexpected "silent failures" where no branch runs and no output is produced.Boolean Expressions Are the Gate
true or false). JavaScript's type coercion can cause tricky bugs if you accidentally test a non-Boolean value.KEY TAKEAWAY
SECTION 3
Visual Explanation — How an If/Else Chain Flows
score = 85, the first diamond (score >= 90) evaluates to false, so control flows down. The second diamond (score >= 80) evaluates to true, so "B" is printed and the entire chain is exited. The remaining conditions are never tested.Notice how each diamond represents one condition check. The TRUE arrow leads to an action block, and after that action runs, control jumps straight to the exit — skipping every diamond below. The FALSE arrow drops down to the next condition. The final else block at the bottom has no diamond because it catches everything that fell through above.
SECTION 4
How If/Else Chains Work Under the Hood
The Anatomy of an If/Else Chain
An if/else chain in JavaScript follows a strict syntax. The keyword if is followed by a condition wrapped in parentheses, then a block of code in curly braces. Additional branches use else if (two words, no hyphen), and the optional catch-all uses else alone. Here is the general pattern:
GENERAL SYNTAX
conditionA, conditionB, conditionC — Boolean expressions evaluated top to bottom. blockA … defaultBlock — the code that runs when the corresponding condition is the first to evaluate to true.
Separate If Statements vs. If/Else-If Chain
A common source of bugs is writing multiple standalone if statements when you actually need an if/else-if chain. With separate if blocks, every condition is tested independently, and multiple blocks can execute. With an if/else-if chain, only the first matching branch runs. Consider these two snippets:
| Separate if Statements | If/Else-If Chain |
|---|---|
if (x > 5) { log("big"); }
if (x > 3) { log("medium"); }
if (x > 0) { log("positive"); } | if (x > 5) { log("big"); }
else if (x > 3) { log("medium"); }
else if (x > 0) { log("positive"); } |
| When x = 7, all three conditions are true, so all three messages print. | When x = 7, only "big" prints because the chain exits after the first match. |
Separate if blocks vs. a single if/else-if chain with x = 7
Common Mistake
if blocks instead of linking them with else if is one of the most frequent bugs beginners introduce. If your branches are meant to be mutually exclusive, always connect them with else if.SECTION 5
Designing Condition Order to Avoid Logic Bugs
The order of your conditions can make or break your program. A shadowed branch occurs when a broader condition appears before a narrower one, causing the narrow branch to become unreachable. This is the single most common logic bug in if/else chains, and it usually produces no error — the program runs, but it gives the wrong answer.
score >= 60 is tested first, so a score of 95 is incorrectly graded as "D." The right panel fixes the bug by placing the narrowest condition (score >= 90) at the top.The Golden Rule of Condition Order
When your conditions test overlapping ranges (like >= thresholds), always arrange them from most restrictive to least restrictive. A condition is more restrictive when fewer values can satisfy it. For numeric thresholds going upward, this means testing the highest value first. For thresholds going downward, test the lowest value first.
- ✓ Overlapping >= checks: Start with the highest threshold. Example: 90, then 80, then 70, then 60.
- ✓ Overlapping <= checks: Start with the lowest threshold. Example: 10, then 20, then 30.
- ✓ Non-overlapping conditions: Order doesn't matter logically, but putting the most common case first can improve readability.
- ✓ Exact-match checks (===): Order is irrelevant since each condition matches exactly one value, but consider using a
switchstatement instead for clarity.
SECTION 6
Worked Example — Movie Ticket Pricing
A movie theater charges different ticket prices based on the customer's age. Children (under 13) pay $8, teens (13–17) pay $10, adults (18–64) pay $14, and seniors (65 and over) pay $9. Let's write a complete if/else chain and then trace through it for a customer who is 16 years old.
Determine Ticket Price for age = 16
- 1
Step 1 — Identify the Conditions and Order
We have four age categories. The boundaries are 13, 18, and 65. Since we are using<for the first check, we start with the youngest group and work upward. This prevents shadowing because each successive branch is only reached when the age is at least as high as the previous boundary.Order: child → teen → adult → senior (ascending) - 2
Step 2 — Write the Code
Here is the complete chain:let age = 16; let price; if (age < 13) { price = 8; } else if (age < 18) { price = 10; } else if (age < 65) { price = 14; } else { price = 9; }Four branches cover every possible age, and every boundary is tested exactly once. - 3
Step 3 — Trace Execution for age = 16
Condition 1:16 < 13→ false. Move to next branch. Condition 2:16 < 18→ true. The engine enters this block and setsprice = 10. All remaining branches (adult and senior) are skipped.price = 10 (teen ticket) - 4
Step 4 — Verify Edge Cases
Edge-case testing is critical. At age = 13: condition 1 is false (13 < 13 is false), condition 2 is true (13 < 18), so price = 10. At age = 18: conditions 1 and 2 are false, condition 3 is true (18 < 65), so price = 14. At age = 65: conditions 1–3 are all false, so the else block sets price = 9. All boundaries behave as expected.Edge cases confirmed: 13 → $10, 18 → $14, 65 → $9 ✓
Pro Tip: Why We Didn't Need && Here
age >= 13 && age < 18. Because the chain exits on the first true branch, reaching the second else if already guarantees age >= 13. The chain's structure handles the lower bound implicitly, making the code cleaner and less error-prone.SECTION 7
If/Else Chains vs. Other Decision Structures
JavaScript offers several ways to make decisions. An if/else chain is the most flexible, but it is not always the best tool. Understanding when to use which structure will make your code more readable and less prone to errors.
| Feature | If/Else Chain | Switch Statement | Ternary Operator |
|---|---|---|---|
| Best for | Range checks, complex Boolean conditions, mixed comparisons | Exact-value matching against a single variable | Simple two-way assignments or inline expressions |
| Readability | Good for 2–5 branches; can become hard to follow beyond that | Excellent when comparing one value to many literals | Compact, but nesting ternaries becomes unreadable quickly |
| Handles ranges? | Yes — its main strength | Not natively; requires workarounds | Only for two-way decisions |
| Fall-through risk | None — branches are mutually exclusive | Yes — forgetting break causes unintended fall-through | None |
| Example use | if (temp > 100) ... else if (temp > 80) ... | switch (day) { case "Mon": ... } | let msg = age >= 18 ? "adult" : "minor"; |
Comparing JavaScript decision structures
WHEN TO CHOOSE WHAT
SECTION 8
Connection to Advanced Patterns
Once you are comfortable with if/else chains, you will encounter more advanced patterns that build on the same core idea of branching. Understanding how your current knowledge connects to these patterns will make the transition smoother when you encounter them in future courses or real-world projects.
| What You Know Now | Advanced Pattern | Why It Matters |
|---|---|---|
| If/else chain with simple conditions | Nested if/else — chains inside chains for multi-dimensional decisions | Needed when two or more independent factors affect the outcome (e.g., age AND membership status) |
| Condition order to avoid shadowing | Guard clauses — early-return statements that handle edge cases before the main logic | Reduces nesting depth and makes functions easier to read in larger codebases |
| Boolean expressions as gates | Short-circuit evaluation — using && and || to combine or replace simple branches | Enables concise one-liner conditions and defensive checks like user && user.name |
| Else as a default handler | Object lookup maps — replacing long chains with a data structure | When you have 10+ exact-match branches, an object lookup is cleaner and faster than a massive if/else chain |
From beginner conditionals to professional patterns
You don't need to master these advanced patterns right now. The key insight is that every advanced branching technique is built on the same top-down, first-match-wins logic you are learning today. If you deeply understand how condition order affects execution, you will find guard clauses, short-circuit evaluation, and lookup maps intuitive when you encounter them.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
temperature = 105:
if (temperature > 60) {
console.log("Nice day");
} else if (temperature > 100) {
console.log("Heat warning!");
}Show answer
temperature > 60 is broader than temperature > 100. Since 105 is greater than 60, the first branch matches and prints "Nice day." The chain then exits, and the "Heat warning!" branch is never evaluated. This is a classic shadowed-branch bug. To fix it, swap the order so temperature > 100 is checked first, because it is the more restrictive condition.Question 2: BASIC CALCULATION
weight that sets a variable shippingCost to the correct amount. What does your code output when weight = 7?Show answer
if (weight < 2) {
shippingCost = 5;
} else if (weight <= 10) {
shippingCost = 10;
} else {
shippingCost = 20;
}
When weight = 7: the first condition (7 < 2) is false, the second condition (7 <= 10) is true, so shippingCost is set to 10. The else block is skipped. Notice we start with the lowest range and work upward. The implicit lower bound of the second branch (weight >= 2) is guaranteed by the chain structure.Question 3: INTERMEDIATE
height and age.Show answer
if (height >= 48 && age >= 8) {
console.log("Enjoy the ride!");
} else if (height >= 48 && age < 8) {
console.log("Come back when you're older.");
} else if (height < 48 && age >= 8) {
console.log("You need to grow a bit more.");
} else {
console.log("Sorry, not yet eligible.");
}
The most specific "both pass" condition comes first. Each subsequent branch handles a unique combination of the two factors. The else block at the end catches the case where both conditions fail. Because none of these conditions overlap, order among the middle two branches doesn't strictly matter, but placing the success case first is a common convention for readability.Question 4: APPLIED
windSpeed holds a number in mph. Display the following advisories: 0–25 → "Calm", 26–50 → "Breezy", 51–74 → "High Wind Warning", 75+ → "Severe Storm Warning". A classmate writes this code:
if (windSpeed <= 74) {
advisory = "High Wind Warning";
} else if (windSpeed <= 50) {
advisory = "Breezy";
} else if (windSpeed <= 25) {
advisory = "Calm";
} else {
advisory = "Severe Storm Warning";
}
Identify the bug, fix the code, and trace through your corrected version for windSpeed = 30.Show answer
windSpeed <= 74) comes first. Any wind speed of 74 or below will always match the first branch, making the "Breezy" and "Calm" branches unreachable. Fixed code:
if (windSpeed >= 75) {
advisory = "Severe Storm Warning";
} else if (windSpeed >= 51) {
advisory = "High Wind Warning";
} else if (windSpeed >= 26) {
advisory = "Breezy";
} else {
advisory = "Calm";
}
Trace for windSpeed = 30: condition 1 (30 >= 75) is false, condition 2 (30 >= 51) is false, condition 3 (30 >= 26) is true → advisory = "Breezy". The remaining else is skipped. We reversed the direction so the most restrictive (highest) threshold is tested first.Question 5: CRITICAL THINKING
&&:
if (score >= 90 && score <= 100) { grade = "A"; }
else if (score >= 80 && score <= 89) { grade = "B"; }
// ...and so on
Compare this approach to the streamlined version that uses only >= checks (as shown in Section 5). Which is better and why? Are there any scenarios where the explicit-range version is actually preferable?Show answer
SUMMARY
Lesson Summary
Summary
An if/else chain lets your JavaScript program choose between multiple paths of execution by testing conditions from top to bottom. The first true condition wins, its code block runs, and all remaining branches are skipped. The optional else block acts as a default safety net, catching any value not handled above. Remember that multiple standalone if statements are independent checks that can all fire, while an if/else if chain guarantees mutual exclusivity.
The most critical skill is condition order. When conditions overlap (such as range thresholds), always place the most specific (narrowest) condition first and the broadest last. Placing a broader condition first creates a shadowed branch — a logic bug that produces no error message but silently gives wrong results. Test your chains with edge-case values at each boundary. When your branches check exact values instead of ranges, consider a switch statement for clarity, and for simple two-way choices, a ternary operator keeps the code compact.