File size: 11,421 Bytes
780c9fe |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
---
title: switch
slug: Web/JavaScript/Reference/Statements/switch
page-type: javascript-statement
browser-compat: javascript.statements.switch
sidebar: jssidebar
---
The **`switch`** statement evaluates an [expression](/en-US/docs/Web/JavaScript/Guide/Expressions_and_operators), matching the expression's value against a series of `case` clauses, and executes [statements](/en-US/docs/Web/JavaScript/Reference/Statements) after the first `case` clause with a matching value, until a `break` statement is encountered. The `default` clause of a `switch` statement will be jumped to if no `case` matches the expression's value.
{{InteractiveExample("JavaScript Demo: switch statement", "taller")}}
```js interactive-example
const expr = "Papayas";
switch (expr) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Mangoes":
case "Papayas":
console.log("Mangoes and papayas are $2.79 a pound.");
// Expected output: "Mangoes and papayas are $2.79 a pound."
break;
default:
console.log(`Sorry, we are out of ${expr}.`);
}
```
## Syntax
```js-nolint
switch (expression) {
case caseExpression1:
statements
case caseExpression2:
statements
// …
case caseExpressionN:
statements
default:
statements
}
```
- `expression`
- : An expression whose result is matched against each `case` clause.
- `caseExpressionN` {{optional_inline}}
- : A `case` clause used to match against `expression`. If the value of `expression` matches the value of any `caseExpressionN`, execution starts from the first statement after that `case` clause until either the end of the `switch` statement or the first encountered `break`.
- `default` {{optional_inline}}
- : A `default` clause; if provided, this clause is executed if the value of `expression` doesn't match any of the `case` clauses. A `switch` statement can only have one `default` clause.
## Description
A `switch` statement first evaluates its expression. It then looks for the first `case` clause whose expression evaluates to the same value as the result of the input expression (using the [strict equality](/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) comparison) and transfers control to that clause, executing all statements following that clause.
The clause expressions are only evaluated when necessary — if a match is already found, subsequent `case` clause expressions will not be evaluated, even when they will be visited by [fall-through](#breaking_and_fall-through).
```js
switch (undefined) {
case console.log(1):
case console.log(2):
}
// Only logs 1
```
If no matching `case` clause is found, the program looks for the optional `default` clause, and if found, transfers control to that clause, executing statements following that clause. If no `default` clause is found, the program continues execution at the statement following the end of `switch`. By convention, the `default` clause is the last clause, but it does not need to be so. A `switch` statement may only have one `default` clause; multiple `default` clauses will result in a {{jsxref("SyntaxError")}}.
### Breaking and fall-through
You can use the [`break`](/en-US/docs/Web/JavaScript/Reference/Statements/break) statement within a `switch` statement's body to break out early, often when all statements between two `case` clauses have been executed. Execution will continue at the first statement following `switch`.
If `break` is omitted, execution will proceed to the next `case` clause, even to the `default` clause, regardless of whether the value of that clause's expression matches. This behavior is called "fall-through".
```js
const foo = 0;
switch (foo) {
case -1:
console.log("negative 1");
break;
case 0: // Value of foo matches this criteria; execution starts from here
console.log(0);
// Forgotten break! Execution falls through
case 1: // no break statement in 'case 0:' so this case will run as well
console.log(1);
break; // Break encountered; will not continue into 'case 2:'
case 2:
console.log(2);
break;
default:
console.log("default");
}
// Logs 0 and 1
```
In the appropriate context, other control-flow statements also have the effect of breaking out of the `switch` statement. For example, if the `switch` statement is contained in a function, then a [`return`](/en-US/docs/Web/JavaScript/Reference/Statements/return) statement terminates the execution of the function body and therefore the `switch` statement. If the `switch` statement is contained in a loop, then a [`continue`](/en-US/docs/Web/JavaScript/Reference/Statements/continue) statement stops the `switch` statement and jumps to the next iteration of the loop.
### Lexical scoping
The `case` and `default` clauses are like [labels](/en-US/docs/Web/JavaScript/Reference/Statements/label): they indicate possible places that control flow may jump to. However, they don't create lexical [scopes](/en-US/docs/Glossary/Scope) themselves (neither do they automatically break out — as demonstrated above). For example:
```js-nolint example-bad
const action = "say_hello";
switch (action) {
case "say_hello":
const message = "hello";
console.log(message);
break;
case "say_hi":
const message = "hi";
console.log(message);
break;
default:
console.log("Empty action received.");
}
```
This example will output the error "Uncaught SyntaxError: Identifier 'message' has already been declared", because the first `const message = 'hello';` conflicts with the second `const message = 'hi';` declaration, even when they're within their own separate case clauses. Ultimately, this is due to both `const` declarations being within the same block scope created by the `switch` body.
To fix this, whenever you need to use `let` or `const` declarations in a `case` clause, wrap it in a block.
```js
const action = "say_hello";
switch (action) {
case "say_hello": {
const message = "hello";
console.log(message);
break;
}
case "say_hi": {
const message = "hi";
console.log(message);
break;
}
default: {
console.log("Empty action received.");
}
}
```
This code will now output `hello` in the console as it should, without any errors.
## Examples
### Using switch
In the following example, if `expr` evaluates to `Bananas`, the program matches the value with case `case 'Bananas'` and executes the associated statement. When `break` is encountered, the program breaks out of `switch` and executes the statement following `switch`. If `break` were omitted, the statement for the `case 'Cherries'` would also be executed.
```js
switch (expr) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Apples":
console.log("Apples are $0.32 a pound.");
break;
case "Bananas":
console.log("Bananas are $0.48 a pound.");
break;
case "Cherries":
console.log("Cherries are $3.00 a pound.");
break;
case "Mangoes":
case "Papayas":
console.log("Mangoes and papayas are $2.79 a pound.");
break;
default:
console.log(`Sorry, we are out of ${expr}.`);
}
console.log("Is there anything else you'd like?");
```
### Putting the default clause between two case clauses
If no match is found, execution will start from the `default` clause, and execute all statements after that.
```js
const foo = 5;
switch (foo) {
case 2:
console.log(2);
break; // it encounters this break so will not continue into 'default:'
default:
console.log("default");
// fall-through
case 1:
console.log("1");
}
```
It also works when you put `default` before all other `case` clauses.
### Taking advantage of fall-through
This method takes advantage of the fact that if there is no `break` below a `case` clause, execution will continue to the next `case` clause regardless if that `case` meets the criteria.
The following is an example of a single operation sequential `case` statement, where four different values perform exactly the same.
```js
const Animal = "Giraffe";
switch (Animal) {
case "Cow":
case "Giraffe":
case "Dog":
case "Pig":
console.log("This animal is not extinct.");
break;
case "Dinosaur":
default:
console.log("This animal is extinct.");
}
```
The following is an example of a multiple-operation sequential `case` clause, where, depending on the provided integer, you can receive different output. This shows you that it will traverse in the order that you put the `case` clauses, and it does not have to be numerically sequential. In JavaScript, you can even mix in definitions of strings into these `case` statements as well.
```js
const foo = 1;
let output = "Output: ";
switch (foo) {
case 0:
output += "So ";
case 1:
output += "What ";
output += "Is ";
case 2:
output += "Your ";
case 3:
output += "Name";
case 4:
output += "?";
console.log(output);
break;
case 5:
output += "!";
console.log(output);
break;
default:
console.log("Please pick a number from 0 to 5!");
}
```
The output from this example:
| Value | Log text |
| ----------------------------------------------------- | --------------------------------- |
| `foo` is `NaN` or not `1`, `2`, `3`, `4`, `5`, or `0` | Please pick a number from 0 to 5! |
| `0` | Output: So What Is Your Name? |
| `1` | Output: What Is Your Name? |
| `2` | Output: Your Name? |
| `3` | Output: Name? |
| `4` | Output: ? |
| `5` | Output: ! |
### An alternative to if...else chains
You may often find yourself doing a series of [`if...else`](/en-US/docs/Web/JavaScript/Reference/Statements/if...else) matches.
```js
if ("fetch" in globalThis) {
// Fetch a resource with fetch
} else if ("XMLHttpRequest" in globalThis) {
// Fetch a resource with XMLHttpRequest
} else {
// Fetch a resource with some custom AJAX logic
}
```
This pattern is not doing a sequence of `===` comparisons, but you can still convert it to a `switch` construct.
```js
switch (true) {
case "fetch" in globalThis:
// Fetch a resource with fetch
break;
case "XMLHttpRequest" in globalThis:
// Fetch a resource with XMLHttpRequest
break;
default:
// Fetch a resource with some custom AJAX logic
break;
}
```
The `switch (true)` pattern as an alternative to `if...else` is especially useful if you want to utilize the fall-through behavior.
```js
switch (true) {
case isSquare(shape):
console.log("This shape is a square.");
// Fall-through, since a square is a rectangle as well!
case isRectangle(shape):
console.log("This shape is a rectangle.");
case isQuadrilateral(shape):
console.log("This shape is a quadrilateral.");
break;
case isCircle(shape):
console.log("This shape is a circle.");
break;
}
```
## Specifications
{{Specifications}}
## Browser compatibility
{{Compat}}
## See also
- {{jsxref("Statements/if...else", "if...else")}}
|