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.
  • break exits the switch; without it, execution falls through to the next case.
  • default is 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 default to catch unexpected values.
  • Always break unless fall-through is intentional — add a comment when omitting.
  • Use block scopes { } in cases when declaring variables with let/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 expression and compare with case values; strict equality requires exact type match.
  • Multiple cases execute — Missing break on a prior case; trace fall-through path.
  • Linter warns on fall-through — Add // falls through comment (ESLint no-fallthrough rule 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.