switch in JavaScript
The switch statement compares an expression against multiple case values and executes the matching block. It is often cleaner than long if-else if chains when comparing a single value against many constants.
Syntax
switch (expression) {
case value1:
// code if expression === value1
break;
case value2:
// code if expression === value2
break;
default:
// code if no case matches
}
Key Rules
- Comparison uses strict equality (
===) — no type coercion. breakexits the switch; without it, execution falls through to the next case.defaultis optional but recommended for handling unexpected values.- Multiple cases can share the same code block via fall-through.
Basic Example: Day of Week
let day = 3;
let dayName;
switch (day) {
case 0:
dayName = "Sunday";
break;
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
default:
dayName = "Invalid day";
}
console.log(dayName); // Wednesday
Fall-Through for Grouped Cases
Intentionally omit break to handle multiple values with one block:
let fruit = "apple";
let color;
switch (fruit) {
case "banana":
case "lemon":
color = "yellow";
break;
case "apple":
case "cherry":
case "strawberry":
color = "red";
break;
case "orange":
color = "orange";
break;
default:
color = "unknown";
}
console.log(color); // red
Always comment intentional fall-through so linters and reviewers understand it is deliberate.
switch(true) for Range Matching
When cases aren’t simple equality, switch on true and use boolean expressions:
let score = 95;
let grade;
switch (true) {
case score >= 90:
grade = 'A';
break;
case score >= 80:
grade = 'B';
break;
case score >= 70:
grade = 'C';
break;
case score >= 60:
grade = 'D';
break;
default:
grade = 'F';
}
console.log(grade); // A
For range logic, if-else if is often more readable — use switch(true) sparingly.
Block Scope in Cases (ES2015+)
Each case does not create its own block scope. Use { } to avoid variable redeclaration errors:
switch (action) {
case "create": {
let message = "Creating...";
console.log(message);
break;
}
case "delete": {
let message = "Deleting..."; // OK — separate block scope
console.log(message);
break;
}
}
Without blocks, let message in two cases causes a SyntaxError.
switch vs if-else if
Prefer switch |
Prefer if-else if |
|---|---|
| Single value vs many constants | Complex boolean conditions |
| String/number enums | Range comparisons |
| HTTP status codes, menu actions | Multiple unrelated variables |
// Good switch use
switch (response.status) {
case 200: handleSuccess(); break;
case 404: handleNotFound(); break;
case 500: handleServerError(); break;
default: handleUnknown();
}
Object Lookup Alternative
For simple value mapping, an object can replace switch:
const STATUS_MESSAGES = {
200: "OK",
404: "Not Found",
500: "Internal Server Error"
};
const message = STATUS_MESSAGES[status] ?? "Unknown Status";
Objects are easier to extend and test; switch is better when cases need multiple statements.
Best Practices
- Always include
defaultto catch unexpected values. - Always
breakunless fall-through is intentional — add a comment when omitting. - Use block scopes
{ }in cases when declaring variables withlet/const. - Keep case bodies short — extract complex logic into functions.
- Don’t switch on mutable objects — comparison is by reference, not value.
Common Mistakes
| Mistake | Result | Fix |
|---|---|---|
Missing break |
Unintended fall-through executes multiple cases | Add break or comment // fallthrough |
switch(x) with string vs number |
No match ("1" !== 1) |
Ensure types match |
Redeclaring let in cases |
SyntaxError | Wrap case body in { } |
No default case |
Silent no-op on unknown input | Add default with error or fallback |
Troubleshooting
- No case executes — Log
typeof expressionand compare with case values; strict equality requires exact type match. - Multiple cases execute — Missing
breakon a prior case; trace fall-through path. - Linter warns on fall-through — Add
// falls throughcomment (ESLintno-fallthroughrule recognizes this).
The switch statement excels at dispatching on discrete values. Combined with disciplined use of break, block scoping, and a default case, it produces clear and maintainable branching logic.