--- 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")}}