Docs
README
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
- •Basic Syntax
- •How Switch Works
- •The break Statement
- •The default Case
- •Fall-Through Behavior
- •Grouping Cases
- •Switch vs If-Else
- •Common Patterns
- •Best Practices
- •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
| Feature | Description |
|---|---|
| Strict Equality | Uses === for comparison |
| Single Expression | Evaluates one expression |
| Sequential Check | Cases are checked in order |
| break Required | Without 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
| Switch | If-Else |
|---|---|
| Single value, multiple exact matches | Multiple different conditions |
| Checking equality only | Range checks, complex conditions |
| Many cases (5+) | Few conditions (2-3) |
| Known, discrete values | Dynamic 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
| Feature | Description |
|---|---|
switch(expr) | Evaluates expression once |
case value: | Matches using strict equality (===) |
break | Exits the switch block |
default | Executes when no case matches |
| Fall-through | Occurs without break |
| Grouping | Multiple 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