2.3 The switch Statement
SLO 2
Describe the principles of structured programming.
Selection has a second shape. A switch dispatches once on a single value instead of re-testing it in every branch, and break is what keeps each case a block with one way in and one way out — omit it and control runs on into the next case.
SLO 4
Explain what an algorithm is and its importance in computer programming.
The same decision can be written as an if...else chain or as a switch, which is the point: the algorithm is the decision, not the syntax you spell it in. Strict comparison matters here too — a case that can never match is a step the algorithm never takes.
Learning Objectives
After this section, you will be able to:
- Recognize when a long
else ifchain is really one value being compared over and over. - Write a
switchstatement withcaseclauses and adefault. - Explain what
breakdoes and predict what happens when it is missing. - Group several
caselabels that share the same code. - Explain why
switchuses strict comparison, and avoid the dead-casebug that follows from it. - Choose between
if...elseandswitchfor a given problem.
2.3.1 One Value, Many Answers
In Section 2.1 you learned to chain conditions with else if. That chain works for any conditions at all, which is exactly why it is the tool you reach for first. But look closely at this one:
▶ Press Run to see the output…
What you should see:
Wednesday
The code is correct. It is also repetitive in a specific way: the word day appears six times, and every single test asks the same question — does day equal this particular value? The only thing that changes from line to line is the value on the right.
When a chain of conditions is really one value being compared against a list of possibilities, JavaScript has a statement built for exactly that shape.
2.3.2 The switch Statement
A switch statement takes one value and compares it, in order, against a list of case values. When it finds a match, it runs the code for that case.
The repetition is not the problem by itself — it is a symptom. Six copies of day === means six chances to typo the variable name, and a typo like if (dat === 4) does not crash. It simply never matches, and Thursday quietly disappears from your program. A switch names the value once, so that class of bug cannot happen.
Here is the day-of-the-week program again:
▶ Press Run to see the output…
What you should see:
Wednesday
Read it top to bottom, the way JavaScript does:
switch (day)— the value being tested, written once.case 1:— isdayequal to1? No. Move on.case 2:— no. Move on.case 3:— yes. Run the code that follows.break;— stop here and leave theswitch.
The default: clause is the else of a switch: it runs when no case matched. It is optional, and by convention it goes last.
A switch statement compares a single value against a list of case values in order and runs the code belonging to the first case that matches. An optional default clause runs when no case matches.
Definition 2.3.1 — A switch statement compares a single value against a list of case values in order and runs the code belonging to the first case that matches. An optional default clause runs when no case matches.
A vending machine takes a selection code and prints what the customer gets.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
What you should see:
Dispensing: pretzels
Change selection to "Z" and run it again. No case matches, so default runs and the customer gets their money back. A switch without a default would simply do nothing at all — which is rarely what you want when a user can type anything.
Chart the vending machine and something useful happens: you get the else if staircase back, with different labels.
Figure 2.3.1 — The vending machine switch. Compare with Figure 2.1.2 — it is the same staircase of comparisons, written shorter.
switch is not a new control structure. It is the same chain of comparisons as an else if ladder, with the repeated selection === ... factored out. The default is the final else -- the box every unmatched value falls into. A switch with no default is a chart with an arrow going nowhere.
Chart the vending machine and something useful happens: you get the else if staircase back, with different labels.
switch is not a new control structure. It is the same chain of comparisons as an else if ladder, with the repeated selection === ... factored out. The default is the final else -- the box every unmatched value falls into. A switch with no default is a chart with an arrow going nowhere.
The thing inside switch (...) does not have to be a plain variable. JavaScript works out the value first, then starts matching.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
What you should see:
Exactly!
2 + 2 is worked out to 4 before any case is checked. The same is true of the case values themselves — case 3 + 1: would be a perfectly legal way to write case 4:, though there is rarely a reason to.
1. What does this print?
▶ Press Run to see the output…
ExcellentGoodGoodthenSee me after class
Solution
b. Good.
"B" matches the second case, so console.log("Good") runs and the break immediately ends the switch. default runs only when nothing matched.
2. Where does default run in this code?
▶ Press Run to see the output…
- It never runs, because it is not last.
- It runs, printing
something else. - It causes an error.
Solution
b. It runs, printing something else.
default is checked only after every case has failed to match, no matter where in the block it is written. Putting it in the middle is legal and confusing — that is why the convention is to put it last, and the convention is worth following.
Write a switch that takes a variable animal and prints the sound it makes: "dog" prints Woof, "cat" prints Meow, "cow" prints Moo, and anything else prints I do not know that animal. Test it with "cat".
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Meow
Try "cow" and then something like "axolotl" to see the default clause do its job.
2.3.3 break and Fall-Through
The break statement is not decoration. Without it, JavaScript does something surprising: once a case matches, execution keeps going through the cases below it, running their code too, without checking any of their values.
That behavior is called fall-through. Here is the vending machine with every break removed:
▶ Press Run to see the output…
What you should see:
Dispensing: chips Dispensing: pretzels Dispensing: cookies Unknown selection. Refunding your money.
One customer, one dollar, three snacks and a refund. case "A" matched, and from that point on JavaScript simply ran every remaining line in the block — including default, which never even got asked whether it should.
Notice that the broken version did not crash, and did not warn you. It ran, printed four lines, and looked like it worked. A missing break is a logic bug, and the tell is always the same — you see output from cases you did not expect. When a switch prints too much, look for the missing break above the surprising line, not at the surprising line itself.
Fall-through is what happens when a matched case has no break: execution continues into the following cases and runs their code without testing their values.
Definition 2.3.2 — Fall-through is what happens when a matched case has no break: execution continues into the following cases and runs their code without testing their values.
Only one break is missing here. Find it by reading the output.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
What you should see:
Intermediate Advanced
case 2 matched and printed, then fell through into case 3 and printed again. It stopped there, because case 3 does have its break. A learner at level 2 is told they are Advanced — a wrong answer that no error message will ever point you to.
One missing break is nearly invisible in the code. On a chart it is a whole extra arrow.
Figure 2.3.2 — The missing break. Case 2 has no arrow to the End, so after printing it walks straight into case 3's box.
Compare the two print boxes. "Beginner" has an arrow straight to End -- that is its break. "Intermediate" has an arrow into "Advanced" instead. That single arrow is the entire bug, and it is the arrow a break would have redirected.
One missing break is nearly invisible in the code. On a chart it is a whole extra arrow.
Compare the two print boxes. "Beginner" has an arrow straight to End -- that is its break. "Intermediate" has an arrow into "Advanced" instead. That single arrow is the entire bug, and it is the arrow a break would have redirected.
1. What does this print?
▶ Press Run to see the output…
oneonethentwoone,two, thenthree
Solution
b. one then two.
case 1 matches and prints one. With no break, execution falls into case 2 and prints two — the value 2 is never compared to x. That case does have a break, so case 3 is never reached.
2. The last case in a switch often has no break. Why is that usually safe?
- JavaScript adds one automatically.
- There is nothing below it to fall into.
breakis only required inside loops.
Solution
b. There is nothing below it to fall into — the switch block ends, so execution leaves anyway.
Many programmers write the final break regardless, so that adding a new case later cannot silently create a fall-through bug. That is a good habit.
The code below should print exactly one line, but it prints two. Fix it.
const fruit = "apple";
switch (fruit) {
case "apple":
console.log("Apples are red or green.");
case "banana":
console.log("Bananas are yellow.");
break;
default:
console.log("Unknown fruit.");
}
Type it into the editor and run it:
▶ Press Run to see the output…
Solution
case "apple" has no break, so it falls through into case "banana".
▶ Press Run to see the output…
Output:
Apples are red or green.
2.3.4 Grouping Cases
Fall-through is not always a mistake. When several values should produce the same result, you can stack their case labels with no code between them and let the first ones fall into the last.
▶ Press Run to see the output…
What you should see:
It is the weekend.
case "Saturday": has no code of its own, so it falls straight through into case "Sunday": and runs its body. Both values reach the same line.
Compare that to the version you wrote in Section 2.1.8:
▶ Press Run to see the output…
Both are correct. Grouped cases are the switch spelling of ||.
Deliberate grouping and an accidental missing break are the same mechanism. The difference a reader can see is whether there is any code between the stacked labels. case "Saturday": immediately followed by case "Sunday": reads as intent; a case with three lines of code and no break reads as an oversight. If you ever want to fall through after running code, say so in a comment — the next person to read it will assume you forgot.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
What you should see:
February has 28 days.
Twelve values, three outcomes. Written as an else if chain, that same logic needs eleven || operators.
Write a switch on a variable letter that prints Vowel for "a", "e", "i", "o", or "u", and Consonant for anything else. Use grouped cases, not ||. Test it with "e".
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Vowel
Only the last of the five labels carries the code and the break; the other four fall into it.
2.3.5 switch Compares Strictly
A case matches using strict equality — the === you met in Section 2.1. The value and the case must be the same type, not just the same-looking content.
This matters more than it sounds, because values that arrive from outside your program are almost always strings.
▶ Press Run to see the output…
What you should see:
Not a valid choice.
The string "3" is not strictly equal to the number 3, so case 3 never matches. It is dead code — a line that can never run, sitting in the middle of your program looking perfectly reasonable.
There are two fixes, and which one is right depends on what the value really is:
▶ Press Run to see the output…
What you should see:
You chose three. Converted: three.
Recall from Section 2.1.2 that == would have matched "3" against 3, because it converts types before comparing. switch gives you no such option — it is always strict. That is a feature, not a limitation: it means a switch never matches something you did not intend. But it does put the burden on you to know what type your value actually is.
1. What does this print?
▶ Press Run to see the output…
matched falsematched zeromatched nothing
Solution
b. matched zero.
0 is falsy (Section 2.1.2), so if (n) would treat it as false — but switch does not test truthiness, it tests ===. A number is not strictly equal to a boolean, so case false fails and case 0 matches.
2. A form field gives you age as the string "18". Which switch header lets case 18: match?
switch (age)switch (Number(age))switch (age === 18)
Solution
b. switch (Number(age)) converts the string to the number 18, which then matches case 18: strictly.
Option a compares "18" to 18 and fails. Option c switches on false — the comparison result — which matches neither case 18: nor anything else sensible.
The code below is meant to print Second place and prints nothing useful instead. Explain why, then fix it without changing the case values.
const place = "2";
switch (place) {
case 1:
console.log("First place");
break;
case 2:
console.log("Second place");
break;
default:
console.log("No medal");
}
Type it into the editor and run it:
▶ Press Run to see the output…
Solution
place is the string "2", and switch compares strictly, so "2" === 2 is false. Every case fails and default runs. Since the cases must stay as numbers, convert the value:
▶ Press Run to see the output…
Output:
Second place
2.3.6 Choosing Between if...else and switch
Neither statement is better. They fit different shapes of problem.
Use a switch when you are comparing one value against a list of specific values:
▶ Press Run to see the output…
What you should see:
You walk north.
Use an if...else chain when the conditions are ranges, involve more than one variable, or are anything other than a plain equality test:
▶ Press Run to see the output…
What you should see:
B
That grade chain cannot become a switch, because score >= 80 is not a value you can list as a case. There is no fixed set of numbers to match — there is a boundary.
The question to ask is not "which one is cleaner". It is: can I write the whole test as a finite list of exact values? If yes, switch says that intent out loud and gets shorter as the list grows. If no — ranges, two variables, &&, || — it is an if...else chain, and forcing a switch onto it produces something worse than what you started with.
1. A program routes a support ticket by its priority, which is always one of "low", "medium", or "high". Which statement fits best?
switch, because one value is compared against a fixed list.if...else, because there are three outcomes.- Either, because they are always interchangeable.
Solution
a. switch. One variable, three exact values, no ranges — this is exactly the shape switch was designed for.
Option c is wrong in one direction: every switch can be rewritten as if...else, but not every if...else can become a switch.
Rewrite this if...else chain as a switch, then say in one sentence how you knew it could be rewritten.
const light = "yellow";
if (light === "green") {
console.log("Go");
} else if (light === "yellow") {
console.log("Slow down");
} else if (light === "red") {
console.log("Stop");
} else {
console.log("Broken light");
}
Write your switch version here:
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Slow down
Every test compared the same variable, light, to one exact string with ===, and there were no ranges and no second variable. The final else became default.
Problem Set 2.3
2.3.1 Which of these else if chains could be rewritten as a switch?
if (score > 90) ... else if (score > 80) ...if (color === "red") ... else if (color === "green") ...if (age > 18 && hasID) ... else if (age > 18) ...
Solution
Step 1 — Identify the shape of each chain: A switch fits when one value is compared against a list of exact values with ===.
Step 2 — Check option a: score > 90 and score > 80 are range comparisons, not equality against fixed values. There is no finite list of numbers to match, so this cannot be a switch.
Step 3 — Check option b: color === "red" and color === "green" compare the same variable to exact string values. This is exactly the shape switch was designed for.
Step 4 — Check option c: The conditions involve two variables (age and hasID) and &&. That is not one value compared against a list, so it cannot be a switch.
Answer: b. Only the chain comparing color to exact values can be rewritten as a switch.
2.3.2 What does this print?
▶ Press Run to see the output…
Solution
Step 1 — Evaluate the switch value: grade is "B".
Step 2 — Compare cases in order: case "A" fails because "B" === "A" is false. case "B" matches because "B" === "B" is true.
Step 3 — Run the matched case and stop: console.log("Good") runs, then break ends the switch immediately. Because of the break, default never runs — it only executes when no case matched.
Answer: It prints Good.
2.3.3 Does a default clause written in the middle of a switch still run when no case matches? Explain.
Solution
Step 1 — Recall how default works: JavaScript checks every case label in order; if none matches, execution jumps to the default: clause wherever it appears in the block. Position does not matter for whether it runs.
Step 2 — Note the convention: Putting default in the middle is legal but confusing to readers, so the convention is to write it last. If a mid-block default has no break, fall-through can also make following cases run unexpectedly after it.
Answer: Yes — default still runs when no case matches, regardless of where it is written. Its position affects readability (and possible fall-through), not whether it executes.
2.3.4 Trace this code and give its exact output.
▶ Press Run to see the output…
Solution
Step 1 — Match the value: x is 1, so case 1 matches and prints one.
Step 2 — Fall through: case 1 has no break, so execution continues into case 2 without checking its value and prints two.
Step 3 — Stop at the break: case 2 has a break, so the switch ends there. case 3 is never reached.
Answer:
one two
2.3.5 Why is a missing break on the last case usually harmless, and why do many programmers write it anyway?
Solution
Step 1 — Why it is harmless: A missing break on the last case causes fall-through into whatever comes next — but below the last case there are no more cases, only the end of the switch block. Execution leaves the switch anyway, so nothing extra runs.
Step 2 — Why programmers write it anyway: If someone later adds a new case below the old last case, the missing break would suddenly create an accidental fall-through bug that silently changes behavior. Writing the final break makes the code safe under future edits.
Answer: It is harmless because there is nothing below the last case to fall into; many programmers include the break anyway so that adding cases later cannot introduce a silent fall-through bug.
2.3.6 What does this print, and why does case false not match?
▶ Press Run to see the output…
Solution
Step 1 — Trace the matching: n is the number 0. switch uses strict comparison (===). A number is never strictly equal to a boolean, so 0 === false is false and case false fails.
Step 2 — Continue down the cases: case 0 matches because 0 === 0 is true, so it prints matched zero and the break ends the switch.
Step 3 — Explain the common confusion: Although 0 is falsy (an if (n) would treat it as false), switch does not test truthiness — it tests strict equality against each case value.
Answer: It prints matched zero. case false does not match because strict equality requires the same type, and the number 0 is not equal to the boolean false.
2.3.7 A form gives you age as the string "18". Write the switch header that lets case 18: match, without changing the case.
▶ Press Run to see the output…
Solution
Step 1 — Diagnose the problem: age is the string "18", and case 18: holds the number 18. Strict comparison means "18" === 18 is false, so the case can never match unless we convert the type.
Step 2 — Convert at the switch header: Wrapping the switched value in Number() converts the string to the number 18 before any case is checked:
▶ Press Run to see the output…
Output:
Adult
Answer: Use switch (Number(age)) { ... } — converting the value to a number lets case 18: match strictly, without changing the case itself.
2.3.8 A ticket's priority is always "low", "medium", or "high". Which statement fits best, and why?
Solution
Step 1 — Examine the problem shape: One variable (priority) is compared against a short, fixed list of exact string values: "low", "medium", "high".
Step 2 — Match shape to tool: A switch exists precisely for "one value, a list of exact possibilities." There are no ranges, no second variable, and no compound conditions.
Answer: A switch fits best, because one value is being compared against a fixed list of exact values — exactly the structure switch was designed for.
2.3.9 Write a switch that takes a variable code and prints the meaning of an HTTP status: 200 prints OK, 404 prints Not Found, 500 prints Server Error, and anything else prints Unknown status.
▶ Press Run to see the output…
Solution
Step 1 — Set up the switch on code: Each status code gets its own case, with default handling anything unrecognized.
▶ Press Run to see the output…
Output:
Not Found
Answer: The switch above prints OK for 200, Not Found for 404, Server Error for 500, and Unknown status for anything else.
2.3.10 Write a switch using grouped cases that prints Weekend for "Saturday" and "Sunday" and Weekday for the other five days. Name all seven days explicitly — do not use default for the weekdays.
▶ Press Run to see the output…
Solution
Step 1 — Group the weekend days: Stack case "Saturday": and case "Sunday": with no code between them so both fall into the same block.
Step 2 — List all five weekdays explicitly: Since the instructions forbid using default for weekdays, each weekday needs its own stacked case label falling into the Weekday print.
▶ Press Run to see the output…
Output:
Weekend
Answer: The switch above groups Saturday and Sunday into one block printing Weekend, and groups Monday–Friday into another block printing Weekday, naming all seven days explicitly.
2.3.11 The code below should print exactly one line but prints three. Fix it.
const size = "small";
switch (size) {
case "small":
console.log("Small: $2");
case "medium":
console.log("Medium: $3");
case "large":
console.log("Large: $4");
break;
}
▶ Press Run to see the output…
Solution
Step 1 — Trace the bug: size is "small", so case "small" matches and prints Small: $2. But that case has no break, so execution falls through into case "medium" and prints Medium: $3, then into case "large" and prints Large: $4 before hitting that case's break. Three lines instead of one.
Step 2 — Fix by adding breaks: Add a break after each case's output so each match stops immediately.
▶ Press Run to see the output…
Output:
Small: $2
Answer: Add break; after the case "small" body (and after case "medium" for safety). Now only Small: $2 prints.
2.3.12 Explain in your own words why case 3: can never run when the switched value came from a text input.
Solution
Step 1 — Where text-input values come from: Values read from a text input arrive as strings — even if the user types digits, the program receives something like "3", not the number 3.
Step 2 — Apply strict comparison: A switch compares with ===, which requires both the same value and the same type. Since the string "3" is never strictly equal to the number 3, case 3: fails every time.
Step 3 — Conclude: No string can ever strictly equal a number, so case 3: is dead code — it looks reasonable but can never run unless the value is converted first (for example with Number(...)).
Answer: Text inputs always produce strings, and switch compares strictly, so a string like "3" can never match the number in case 3: — the case is unreachable dead code.
2.3.13 Rewrite this switch as an if...else chain.
const command = "north";
switch (command) {
case "north":
console.log("You walk north.");
break;
case "south":
console.log("You walk south.");
break;
default:
console.log("You cannot go that way.");
}
▶ Press Run to see the output…
Solution
Step 1 — Convert each case to an equality test: Each case X: becomes if/else if (command === X), and default becomes the final else.
▶ Press Run to see the output…
Output:
You walk north.
Answer: The if...else chain above behaves identically to the original switch: it tests command against "north", then "south", and falls back to the final else for anything else.
2.3.14 Explain why the grade chain in Section 2.3.6 (score >= 90, score >= 80, …) cannot be rewritten as a switch.
Solution
Step 1 — Look at what the conditions test: The chain uses score >= 90, score >= 80, score >= 70 — these are range comparisons, not comparisons against exact values.
Step 2 — Ask the key question: A switch requires the whole test to be expressible as a finite list of exact values to match one switched value against. Here there is no such list: infinitely many scores satisfy score >= 80, and the boundaries (90, 80, 70) are thresholds, not specific values to match.
Step 3 — Conclude: Forcing this into a switch would mean listing every possible score from 0 to 100 as a case — absurd and fragile — or grouping hundreds of cases per grade band, which is worse than the original chain.
Answer: It cannot be rewritten as a switch because the conditions are ranges (>= boundaries), not equality checks against a finite list of exact values — and ranges are exactly what switch cannot express.
Key Terms
switch statement -- A statement that compares one value against a list of case values in order and runs the code for the first match.
case -- A labelled branch inside a switch giving one value to compare against and the code to run on a match.
default -- The optional clause in a switch that runs when no case matched; the switch equivalent of else.
break -- The statement that ends a switch immediately, preventing execution from continuing into the cases below.
Fall-through -- Execution continuing from a matched case into the following cases because no break stopped it. A bug when accidental, a technique when cases are deliberately grouped.
Grouped cases -- Several case labels stacked with no code between them so they all run the same block.
Strict equality (===) -- Comparison that requires the same type as well as the same value; the comparison a switch always uses.
Dead code -- A line or branch that can never run, such as case 3: when the switched value is always a string.