JAVASCRIPT / CONDITIONALS
if, else if, and else branches
Trace an if/else if/else chain to see which single branch runs, and order overlapping tests so every branch stays reachable.
What you will learn
- Trace a chain top to bottom and name the one branch that runs for a given input
- Order overlapping tests narrowest first so no else if branch becomes unreachable
- Use one else if chain, not separate ifs, when exactly one case should apply
- Predict which conditions get skipped once an earlier condition is truthy
Understanding if, else if, and else branches
An if/else if/else chain is a single decision, not a list of independent questions. JavaScript evaluates the first condition, coerces its result to a boolean, and if that is true it runs that block and jumps past everything else in the chain. Only when a condition is false does it move on to the next one, and a trailing else runs with no test at all, which is what guarantees that some branch always executes.
There is no `else if` operator in the language. `else` takes exactly one statement as its body, and an `if` statement is a statement, so `else if` is just an `if` nested inside the previous `else` with the indentation flattened out. That nesting is the mechanical reason at most one branch can ever run, and it is also why a dangling `else` attaches to the closest `if` that does not already have one.
Because the tests are read in source order, the order you write them in is the priority you are choosing. When conditions overlap, such as `score >= 60` and `score >= 90`, whichever appears first swallows the inputs both would match, and the later branch becomes dead code the engine will never enter. The flip side is that conditions after the winning one are never evaluated at all, so a condition that increments a counter, calls an API, or would throw on a missing property behaves differently depending on where you place it in the chain.
function test(label, result) {
console.log("checking " + label);
return result;
}
function grade(score) {
if (test("score >= 90", score >= 90)) {
return "A";
} else if (test("score >= 80", score >= 80)) {
return "B";
} else if (test("score >= 70", score >= 70)) {
return "C";
} else {
return "F";
}
}
console.log("result for 85: " + grade(85));
console.log("result for 50: " + grade(50));A chain tests conditions top to bottom and stops at the first truthy one, so the order you write the branches in is the priority the program gets.
Worked examples
A branch that can never run
Shows how a broad condition placed first makes a narrower later branch unreachable.
function describe(n) {
if (n > 0) {
return "positive";
} else if (n > 100) {
return "huge";
} else {
return "not positive";
}
}
console.log("5 -> " + describe(5));
console.log("500 -> " + describe(500));
console.log("-2 -> " + describe(-2));Example explained
Line 1`n > 0` is checked first, and 500 satisfies it, so the function returns "positive" immediately.
Line 2The `n > 100` test is never reached for any input, because every number above 100 is also above 0.
Line 3No error or warning is produced; the branch is simply dead, which is why this bug survives testing.
Line 4Swapping the first two tests makes "huge" reachable and leaves "positive" for 1 through 100.
Separate ifs versus one chain
Demonstrates that independent if statements can both run while chained branches are mutually exclusive.
const temp = 105;
let alerts = 0;
if (temp > 100) {
alerts += 1;
}
if (temp > 90) {
alerts += 1;
}
console.log("separate ifs: " + alerts);
alerts = 0;
if (temp > 100) {
alerts += 1;
} else if (temp > 90) {
alerts += 1;
}
console.log("one chain: " + alerts);Example explained
Line 1The two standalone `if` statements are unrelated, so both conditions are evaluated and both bodies run.
Line 2In the chained version the `else if` condition is only evaluated when `temp > 100` is false, which it is not here.
Line 3The chain therefore adds 1 exactly once, matching the intent of "pick one severity level".
Line 4The same difference shows up with assignment: separate ifs let a later branch overwrite an earlier value.
else if is a nested if
Proves a flat chain and an explicitly nested version compute identical results.
function chained(n) {
if (n >= 10) return "gold";
else if (n >= 5) return "silver";
else return "bronze";
}
function nested(n) {
if (n >= 10) {
return "gold";
} else {
if (n >= 5) {
return "silver";
} else {
return "bronze";
}
}
}
for (const n of [12, 7, 2]) {
console.log(`${n}: chained=${chained(n)} nested=${nested(n)} same=${chained(n) === nested(n)}`);
}Example explained
Line 1`nested` writes out what the parser already builds for `chained`: an if inside the previous else.
Line 2Because the second test lives inside the first else, it can only run when the first test failed.
Line 3The single-statement branches in `chained` need no braces, since `return` is one statement.
Line 4Identical results for all three inputs confirm the flat style is formatting, not different behaviour.
Important notes
A chain with no final `else` can match nothing at all, which leaves any variable you meant to assign inside it holding its previous value or `undefined`.
`else` binds to the nearest `if` that does not already have one, so nesting a braceless `if` inside a branch can attach your `else` to the wrong test.
Common mistakes
Putting the loosest range first, as in `if (score >= 60) ... else if (score >= 90)`: every passing score stops at the first branch, so top scores silently get the lowest passing label.
Writing three separate `if` statements for cases meant to be exclusive: two or more bodies run for overlapping input, and the last assignment overwrites the correct earlier one.
Dropping the braces and then adding a second line, as in `if (ready) start(); logStart();`: only `start()` is conditional, so `logStart()` runs on every pass.
Try it yourself
Change, predict, then run
In a browser console, write a function that maps an hour from 0 to 23 to "night", "morning", "afternoon", or "evening" using one if/else if/else chain, and check it with 0, 9, 15, and 21. Then move the broadest test to the top and note which branch stops being reachable.
Open the JavaScript workspaceCheck your understanding
A chain tests `if (temp > 0)` first and `else if (temp > 30)` second, and the second branch never runs. Why, and what fixes it?
- Every temp above 30 is also above 0, so the first test always matches first; move `temp > 30` ahead of `temp > 0`.
- Both tests are true, so the chain keeps the last matching branch; add `break` so it stops at the first one.
- A chain supports at most two conditions, so the third clause is ignored; split it into a second, separate chain.
- `else if` is only evaluated when the previous branch's body is empty, so give the first branch a `return`.
Show answer
The conditions overlap, and the chain stops at the first truthy test, so the broader `temp > 0` claims every input the narrower test wanted; ordering the specific test first restores it. Option 2 is tempting because it feels like the engine picks the best or last match, but only one branch can ever run, later conditions are not even evaluated, and `break` is not part of `if` syntax.