JavaScript Switch Statement
Switch Statement Basics
The switch statement evaluates one expression and then compares the result against a list of cases using strict equality. When a match is found, execution jumps to that case and continues until a break statement exits the block. The default case runs if nothing matches. It's a cleaner alternative to long if/else-if chains when you're comparing a single variable against many fixed values - the code reads more like a list of options than a nested series of conditions.
1let day = "Monday";
2
3switch (day) {
4 case "Monday":
5 console.log("Start of week");
6 break;
7 case "Friday":
8 console.log("Weekend is near");
9 break;
10 default:
11 console.log("It's a regular day");
12}
13// Output: "Start of week"
14// Execution: evaluates 'day', matches "Monday", runs that case, break exitsSwitch Statement Components
Expression evaluation- The expression in parentheses is evaluated once at the start. The result is compared against each case.Strict equality- Cases are matched using === - both value and type must match. '5' and 5 are different.break statement- Exits the switch block. Without it, execution falls through to the next case.default case- Runs when no case matches. Optional, but worth including for unexpected values.
Switch Statement Syntax
The switch expression can be any value - a string, number, or the result of a function call. Each case value is compared against it with ===. A useful pattern is switch(true) where you put boolean expressions in the cases instead of literal values, which lets you do range comparisons in a switch structure. It looks a bit unusual but it works, and sometimes reads better than a long if/else-if chain when each branch has a clear label.
1// String switch
2let fruit = "apple";
3switch (fruit) {
4 case "apple": console.log("Red fruit"); break;
5 case "banana": console.log("Yellow fruit"); break;
6 case "orange": console.log("Orange fruit"); break;
7 default: console.log("Unknown fruit");
8}
9
10// Number switch
11let month = 3;
12switch (month) {
13 case 1: console.log("January"); break;
14 case 2: console.log("February"); break;
15 case 3: console.log("March"); break; // executes
16 default: console.log("Other month");
17}
18
19// Grouped cases - multiple values, one outcome
20let grade = "B";
21switch (grade) {
22 case "A":
23 case "B":
24 case "C":
25 console.log("You passed!"); // A, B, or C all reach this
26 break;
27 case "D":
28 case "F":
29 console.log("You failed");
30 break;
31 default:
32 console.log("Invalid grade");
33}
34
35// switch(true) for range comparisons
36let score = 85;
37switch (true) {
38 case score >= 90: console.log("Grade: A"); break;
39 case score >= 80: console.log("Grade: B"); break; // executes
40 case score >= 70: console.log("Grade: C"); break;
41 default: console.log("Grade: F");
42}Syntax Components
switch (expression)- Evaluates once. Can be a variable, function call, or any expression.case value:- Compared to expression using ===. Must be a constant or literal - not another expression.break;- Exits the switch block. Without it, execution continues into the next case.default:- Handles values that don't match any case. Optional but recommended.
Break Statements and Fall-Through
Fall-through is what happens when a case doesn't have a break - execution continues into the next case body regardless of whether that case matched. It's the most common source of switch bugs. Accidental fall-through produces no error, just wrong output, and can be genuinely confusing to debug. Intentional fall-through is a different story - grouping multiple cases that share behavior is a legitimate and readable pattern. When you intentionally let a case fall through, add a comment saying so, otherwise anyone reading the code will assume it's a bug.
1// Accidental fall-through - a bug
2let number = 1;
3switch (number) {
4 case 1:
5 console.log("Number is 1");
6 // forgot break
7 case 2:
8 console.log("Number is 2"); // also executes!
9 break;
10}
11// Prints: "Number is 1" AND "Number is 2"
12
13// Intentional fall-through - for grouped behavior
14let day = "Monday";
15switch (day) {
16 case "Monday":
17 console.log("Start of work week");
18 // fall through - Monday is also a workday
19 case "Tuesday":
20 case "Wednesday":
21 case "Thursday":
22 console.log("It's a workday");
23 break;
24 case "Friday":
25 console.log("Almost weekend!");
26 break;
27 case "Saturday":
28 case "Sunday":
29 console.log("Weekend!");
30 break;
31}
32// For Monday: both messages print (intentional)
33
34// Using return instead of break in functions
35function getSeason(month) {
36 switch (month) {
37 case 12: case 1: case 2: return "Winter";
38 case 3: case 4: case 5: return "Spring";
39 case 6: case 7: case 8: return "Summer";
40 case 9: case 10: case 11: return "Fall";
41 default: return "Invalid month";
42 }
43}
44console.log(getSeason(1)); // "Winter"Switch vs If-Else: When to Use Each
Switch is the right tool when you're comparing one variable against a set of discrete, known values - days of the week, HTTP status codes, command names, user roles. It reads like a list of options and groups related cases cleanly. If-else is better for range checks, complex boolean conditions involving multiple variables, or when you only have two or three branches. One pattern worth knowing: the object lookup alternative to long switch statements, where you store handlers in an object and look them up by key - it's more concise when you have many cases that each call a function.
1// Switch is cleaner for discrete value matching
2const direction = "north";
3switch (direction) {
4 case "north": console.log("Moving up"); break;
5 case "south": console.log("Moving down"); break;
6 case "east": console.log("Moving right"); break;
7 case "west": console.log("Moving left"); break;
8 default: console.log("Invalid direction");
9}
10
11// If-else is better for range checks
12const temperature = 25;
13if (temperature > 30) console.log("Hot");
14else if (temperature > 20) console.log("Warm"); // executes
15else if (temperature > 10) console.log("Cool");
16else console.log("Cold");
17
18// Switch with grouped weekday/weekend cases
19const today = "Monday";
20switch (today) {
21 case "Monday": case "Tuesday": case "Wednesday":
22 case "Thursday": case "Friday":
23 console.log("Weekday");
24 break;
25 case "Saturday": case "Sunday":
26 console.log("Weekend");
27 break;
28}
29// Cleaner than: if (day === "Monday" || day === "Tuesday" || ...)
30
31// Object lookup as an alternative for many cases
32const STATUS = {
33 pending: () => console.log("Processing..."),
34 completed: () => console.log("Done!"),
35 failed: () => console.log("Failed")
36};
37
38const currentStatus = "pending";
39const handler = STATUS[currentStatus];
40if (handler) handler();
41else console.log("Unknown status");Advanced Switch Patterns
A few patterns come up frequently in real code: using constants for case values to prevent typos (a mistyped string case just silently never matches), nesting a switch inside a case for subcategory logic, and throwing errors in the default case when an unexpected value should be treated as a bug rather than ignored. The async switch pattern for HTTP status codes is common in API response handling - each status code maps to a different response path.
1// Constants for case values prevent silent typos
2const ACTIONS = {
3 CREATE: "CREATE",
4 UPDATE: "UPDATE",
5 DELETE: "DELETE"
6};
7
8const action = ACTIONS.CREATE;
9switch (action) {
10 case ACTIONS.CREATE: console.log("Creating"); break;
11 case ACTIONS.UPDATE: console.log("Updating"); break;
12 case ACTIONS.DELETE: console.log("Deleting"); break;
13 default: throw new Error(`Unknown action: ${action}`);
14}
15
16// Throwing in default - treat unexpected values as bugs
17function processCommand(type) {
18 switch (type) {
19 case "create": return "Created";
20 case "update": return "Updated";
21 case "delete": return "Deleted";
22 default:
23 throw new Error(`Unknown command: ${type}`);
24 }
25}
26
27// Nested switch for category/subcategory
28const category = "electronics";
29const subcategory = "phone";
30switch (category) {
31 case "electronics":
32 switch (subcategory) {
33 case "phone": console.log("Smartphones"); break;
34 case "laptop": console.log("Laptops"); break;
35 }
36 break;
37 case "clothing":
38 console.log("Fashion items");
39 break;
40}
41
42// HTTP status code handling
43async function handleResponse(statusCode) {
44 switch (statusCode) {
45 case 200: case 201: return "Success";
46 case 400: return "Bad Request";
47 case 401: return "Unauthorized";
48 case 404: return "Not Found";
49 case 500: return "Server Error";
50 default: return `Unexpected status: ${statusCode}`;
51 }
52}
53handleResponse(200).then(console.log); // "Success"Common Switch Mistakes
Forgetting break is the most common switch mistake, and the worst part is it produces no error - just incorrect output that can be hard to trace. The type mismatch mistake is similar: switch uses === so comparing a string value against a number case silently falls through to default. The duplicate case mistake is safer - the second case technically runs but shadows the first, which is confusing. And using switch for two or three conditions is unnecessary verbosity where a simple if-else would be clearer.
1// MISTAKE: Forgetting break - silent wrong output
2let n = 1;
3switch (n) {
4 case 1:
5 console.log("One");
6 // no break!
7 case 2:
8 console.log("Two"); // also runs
9 break;
10}
11// Prints "One" AND "Two" - hard to spot
12
13// FIX: always add break
14switch (n) {
15 case 1: console.log("One"); break;
16 case 2: console.log("Two"); break;
17}
18
19// MISTAKE: Type mismatch - switch uses ===
20const input = "5"; // string
21switch (input) {
22 case 5: // number - won't match
23 console.log("Matched");
24 break;
25 default:
26 console.log("No match"); // this runs
27}
28
29// FIX: convert type before switch
30switch (Number(input)) {
31 case 5: console.log("Matched"); break; // now works
32}
33
34// MISTAKE: Repeated case bodies instead of grouping
35const day = "Monday";
36switch (day) {
37 case "Monday": console.log("Weekday"); break; // repetitive
38 case "Tuesday": console.log("Weekday"); break;
39 case "Wednesday": console.log("Weekday"); break;
40}
41
42// FIX: group the cases
43switch (day) {
44 case "Monday": case "Tuesday": case "Wednesday":
45 console.log("Weekday");
46 break;
47}
48
49// MISTAKE: Switch for 2-3 cases where if-else is cleaner
50const color = "red";
51switch (color) {
52 case "red": console.log("Red"); break;
53 case "blue": console.log("Blue"); break;
54 default: console.log("Other");
55}
56
57// BETTER: simple if-else
58if (color === "red") console.log("Red");
59else if (color === "blue") console.log("Blue");
60else console.log("Other");Switch Best Practices
The habits that matter most: always include a default case because unexpected values should be handled, not silently ignored; always add break unless fall-through is intentional and commented; use named constants for case values to prevent typo bugs where a mistyped string silently falls through; and keep case bodies short - if a case needs more than a few lines, extract it to a named function. For very long switch statements with fifteen or more cases, an object lookup is worth considering.
1// Always include default - handle unexpected values
2const status = "pending";
3switch (status) {
4 case "pending": console.log("Processing..."); break;
5 case "completed": console.log("Done!"); break;
6 default:
7 console.log("Unexpected status:", status); // don't silently ignore
8 break;
9}
10
11// Named constants prevent typo bugs
12const ORDER_STATUS = {
13 PENDING: "PENDING",
14 SHIPPED: "SHIPPED",
15 DELIVERED: "DELIVERED",
16 CANCELLED: "CANCELLED"
17};
18
19const orderStatus = ORDER_STATUS.PENDING;
20switch (orderStatus) {
21 case ORDER_STATUS.PENDING: console.log("Processing"); break;
22 case ORDER_STATUS.SHIPPED: console.log("On the way"); break;
23 case ORDER_STATUS.DELIVERED: console.log("Delivered"); break;
24 case ORDER_STATUS.CANCELLED: console.log("Cancelled"); break;
25 default: console.log("Unknown status"); break;
26}
27
28// Extract complex case logic to functions
29function handleUserAction(action, user) {
30 switch (action) {
31 case "login": return performLogin(user); // short, descriptive
32 case "logout": return performLogout(user);
33 case "update": return updateProfile(user);
34 default: throw new Error(`Unknown action: ${action}`);
35 }
36}
37
38// Comment intentional fall-through
39const userLevel = "premium";
40switch (userLevel) {
41 case "admin":
42 console.log("Admin privileges");
43 // fall through - admins also get premium features
44 case "premium":
45 console.log("Premium features");
46 // fall through - premium users get basic features too
47 case "basic":
48 console.log("Basic features");
49 break;
50 default:
51 console.log("No access");
52 break;
53}
54
55// Object lookup for many cases - an alternative worth knowing
56const statusHandlers = {
57 pending: () => "Processing...",
58 completed: () => "Done!",
59 failed: () => "Failed",
60 cancelled: () => "Cancelled"
61};
62
63const handle = statusHandlers[status];
64console.log(handle ? handle() : "Unknown status");