Docs

4.2-Switch

4.2 Switch Statements

Overview

The switch statement evaluates an expression and executes code associated with the matching case. It's often cleaner than multiple if-else if chains when comparing a single value against multiple possibilities.


Table of Contents

  1. Basic Syntax
  2. How Switch Works
  3. The break Statement
  4. The default Case
  5. Fall-Through Behavior
  6. Grouping Cases
  7. Switch vs If-Else
  8. Common Patterns
  9. Best Practices
  10. Limitations

Basic Syntax

switch (expression) {
  case value1:
    // code to execute if expression === value1
    break;
  case value2:
    // code to execute if expression === value2
    break;
  case value3:
    // code to execute if expression === value3
    break;
  default:
  // code to execute if no case matches
}

Simple Example

const day = 3;
let dayName;

switch (day) {
  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;
  case 7:
    dayName = 'Sunday';
    break;
  default:
    dayName = 'Invalid day';
}

console.log(dayName); // "Wednesday"

How Switch Works

        ┌──────────────────┐
        │ Evaluate         │
        │ expression       │
        └────────┬─────────┘
                 │
        ┌────────▼─────────┐
        │ Compare with     │
        │ case value1      │───── Match? ───▶ Execute case 1 code
        └────────┬─────────┘
                 │ No match
        ┌────────▼─────────┐
        │ Compare with     │
        │ case value2      │───── Match? ───▶ Execute case 2 code
        └────────┬─────────┘
                 │ No match
                 ▼
              ... more cases ...
                 │
        ┌────────▼─────────┐
        │ default          │───▶ Execute default code
        └──────────────────┘

Key Points

FeatureDescription
Strict EqualityUses === for comparison
Single ExpressionEvaluates one expression
Sequential CheckCases are checked in order
break RequiredWithout break, execution continues

The break Statement

break exits the switch block. Without break, execution "falls through" to the next case!

const fruit = 'apple';

// WITH break (correct)
switch (fruit) {
  case 'apple':
    console.log("It's an apple");
    break; // Stops here
  case 'banana':
    console.log("It's a banana");
    break;
  default:
    console.log('Unknown fruit');
}
// Output: "It's an apple"

// WITHOUT break (fall-through)
switch (fruit) {
  case 'apple':
    console.log("It's an apple");
  // No break! Falls through...
  case 'banana':
    console.log("It's a banana");
  // No break! Falls through...
  default:
    console.log('Unknown fruit');
}
// Output: "It's an apple"
//         "It's a banana"
//         "Unknown fruit"

The default Case

The default case executes when no other case matches. It's optional but recommended.

const color = 'purple';

switch (color) {
  case 'red':
    console.log('#FF0000');
    break;
  case 'green':
    console.log('#00FF00');
    break;
  case 'blue':
    console.log('#0000FF');
    break;
  default:
    console.log('Color not found');
}
// Output: "Color not found"

Position of default

The default case can be placed anywhere, but it's conventionally at the end:

// Default in the middle (works but unusual)
switch (value) {
  case 1:
    console.log('One');
    break;
  default:
    console.log('Default');
    break; // break still needed!
  case 2:
    console.log('Two');
    break;
}

Fall-Through Behavior

Fall-through can be used intentionally for grouping:

const month = 2;
let season;

switch (month) {
  case 12:
  case 1:
  case 2:
    season = 'Winter';
    break;
  case 3:
  case 4:
  case 5:
    season = 'Spring';
    break;
  case 6:
  case 7:
  case 8:
    season = 'Summer';
    break;
  case 9:
  case 10:
  case 11:
    season = 'Fall';
    break;
  default:
    season = 'Invalid month';
}

console.log(season); // "Winter"

Intentional Fall-Through Pattern

const command = 'start';

switch (command) {
  case 'start':
    console.log('Starting...');
  // Intentionally falls through
  case 'resume':
    console.log('Resuming operation');
    break;
  case 'stop':
    console.log('Stopping...');
    break;
}
// If command is "start": "Starting..." then "Resuming operation"
// If command is "resume": only "Resuming operation"

Grouping Cases

Multiple cases can share the same code block:

const char = 'e';
let type;

switch (char.toLowerCase()) {
  case 'a':
  case 'e':
  case 'i':
  case 'o':
  case 'u':
    type = 'vowel';
    break;
  default:
    type = 'consonant';
}

console.log(`'${char}' is a ${type}`); // "'e' is a vowel"

Days Example

const day = 'Saturday';
let dayType;

switch (day) {
  case 'Monday':
  case 'Tuesday':
  case 'Wednesday':
  case 'Thursday':
  case 'Friday':
    dayType = 'Weekday';
    break;
  case 'Saturday':
  case 'Sunday':
    dayType = 'Weekend';
    break;
  default:
    dayType = 'Invalid day';
}

console.log(dayType); // "Weekend"

Switch vs If-Else

When to Use Switch

SwitchIf-Else
Single value, multiple exact matchesMultiple different conditions
Checking equality onlyRange checks, complex conditions
Many cases (5+)Few conditions (2-3)
Known, discrete valuesDynamic or computed conditions

Comparison Example

// Switch - clean for exact value matching
function getDayName(num) {
  switch (num) {
    case 1:
      return 'Monday';
    case 2:
      return 'Tuesday';
    case 3:
      return 'Wednesday';
    case 4:
      return 'Thursday';
    case 5:
      return 'Friday';
    case 6:
      return 'Saturday';
    case 7:
      return 'Sunday';
    default:
      return 'Invalid';
  }
}

// If-Else - better for ranges
function getGrade(score) {
  if (score >= 90) return 'A';
  if (score >= 80) return 'B';
  if (score >= 70) return 'C';
  if (score >= 60) return 'D';
  return 'F';
}

// If-Else - required for complex conditions
function classify(person) {
  if (person.age >= 18 && person.hasLicense) {
    return 'Can drive';
  } else if (person.age >= 16 && person.hasPermit) {
    return 'Can drive with supervision';
  } else {
    return 'Cannot drive';
  }
}

Common Patterns

1. Return from Switch

function getColor(status) {
  switch (status) {
    case 'success':
      return 'green';
    case 'warning':
      return 'yellow';
    case 'error':
      return 'red';
    default:
      return 'gray';
  }
}

2. Switch with Expressions

// Switch on an expression
function getPriceCategory(price) {
  switch (
    true // Switch on true!
  ) {
    case price < 10:
      return 'cheap';
    case price < 50:
      return 'moderate';
    case price < 100:
      return 'expensive';
    default:
      return 'luxury';
  }
}

console.log(getPriceCategory(25)); // "moderate"

3. Action Handler

function handleAction(action, data) {
  switch (action.type) {
    case 'ADD':
      return [...data, action.payload];
    case 'REMOVE':
      return data.filter((item) => item.id !== action.payload);
    case 'UPDATE':
      return data.map((item) =>
        item.id === action.payload.id ? action.payload : item
      );
    case 'CLEAR':
      return [];
    default:
      return data;
  }
}

4. State Machine

function nextState(currentState, event) {
  switch (currentState) {
    case 'idle':
      switch (event) {
        case 'start':
          return 'running';
        case 'reset':
          return 'idle';
        default:
          return currentState;
      }
    case 'running':
      switch (event) {
        case 'pause':
          return 'paused';
        case 'stop':
          return 'idle';
        default:
          return currentState;
      }
    case 'paused':
      switch (event) {
        case 'resume':
          return 'running';
        case 'stop':
          return 'idle';
        default:
          return currentState;
      }
    default:
      return currentState;
  }
}

5. Type Checking

function process(value) {
  switch (typeof value) {
    case 'string':
      return value.toUpperCase();
    case 'number':
      return value * 2;
    case 'boolean':
      return !value;
    case 'object':
      if (Array.isArray(value)) {
        return value.length;
      }
      return Object.keys(value).length;
    default:
      return value;
  }
}

Best Practices

1. Always Include default

// ✅ Good - handles unexpected values
switch (status) {
  case 'active':
    // ...
    break;
  case 'inactive':
    // ...
    break;
  default:
    console.warn(`Unknown status: ${status}`);
}

2. Always Use break (Unless Intentional)

// ✅ Good - explicit break
switch (value) {
  case 1:
    doSomething();
    break;
  case 2:
    doSomethingElse();
    break;
}

// If fall-through is intentional, comment it
switch (value) {
  case 1:
    prepare();
  // falls through
  case 2:
    execute();
    break;
}

3. Use Braces for Complex Cases

switch (action) {
  case 'create': {
    const newItem = { id: generateId() };
    items.push(newItem);
    break;
  }
  case 'delete': {
    const index = items.findIndex((i) => i.id === id);
    items.splice(index, 1);
    break;
  }
}

4. Consider Object Lookup Instead

// Switch approach
function getStatusText(code) {
  switch (code) {
    case 200:
      return 'OK';
    case 404:
      return 'Not Found';
    case 500:
      return 'Server Error';
    default:
      return 'Unknown';
  }
}

// Object lookup approach (often cleaner)
const statusTexts = {
  200: 'OK',
  404: 'Not Found',
  500: 'Server Error',
};

function getStatusText(code) {
  return statusTexts[code] || 'Unknown';
}

Limitations

1. Strict Equality Only

const num = '5';

switch (num) {
  case 5: // Won't match! "5" !== 5
    console.log('Five');
    break;
  case '5': // This matches
    console.log('String five');
    break;
}

2. Cannot Use Range Comparisons Directly

// ❌ Won't work as expected
switch (score) {
  case score >= 90: // This compares against true/false!
    console.log('A');
    break;
}

// ✅ Use switch(true) pattern
switch (true) {
  case score >= 90:
    console.log('A');
    break;
  case score >= 80:
    console.log('B');
    break;
}

3. Expression Evaluated Once

let counter = 0;

function getNext() {
  return ++counter;
}

// getNext() is called only ONCE
switch (getNext()) {
  case 1:
    console.log('First call');
    break;
  case 2:
    console.log('Second call'); // Never reached in this switch
    break;
}

Summary

FeatureDescription
switch(expr)Evaluates expression once
case value:Matches using strict equality (===)
breakExits the switch block
defaultExecutes when no case matches
Fall-throughOccurs without break
GroupingMultiple cases can share code

When to Use

  • ✅ Comparing one value against many exact matches
  • ✅ Handling discrete, known values
  • ✅ State machines and action handlers
  • ❌ Range comparisons (use if-else)
  • ❌ Complex conditions (use if-else)
  • ❌ Two or three simple conditions (use if-else)

Next Steps

  • Practice with the examples in examples.js
  • Complete the exercises in exercises.js
  • Learn about loops for repetitive code execution
.2 Switch - JavaScript Tutorial | DeepML