• JavaScript
  • JavaScript
  • Tutorials and guides
  • Beginner's tutorials
    1. JavaScript Guide
      1. Loops and iteration
      2. Representing dates & times
      3. Working with objects
      4. Iterators and generators
      5. Asynchronous JavaScript
      6. Equality comparisons and sameness
      7. Meta programming
      8. AggregateError
      9. AsyncGenerator
      10. BigInt
      11. DataView
      12. encodeURI()
      13. escape() Deprecated
      14. Float16Array
      15. Generator
      16. Int8Array
      17. InternalError Non-standard
      18. Iterator
      19. NaN
      20. parseInt()
      21. ReferenceError
      22. SharedArrayBuffer
      23. Temporal Experimental
      24. Uint8ClampedArray
      25. unescape() Deprecated
      26. WeakSet
  • Assignment (=)
  • Bitwise AND (&)
  • Bitwise OR assignment (|=)
  • Comma operator (,)
  • Destructuring
  • Exponentiation (**)
  • Greater than (>)
  • import.meta.resolve()
  • Inequality (!=)
  • Less than (<)
  • Logical NOT (!)
  • Multiplication assignment (*=)
  • Nullish coalescing assignment (??=)
  • Optional chaining (?.)
  • Right shift (>>)
  • Strict inequality (!==)
  • this
  • Unsigned right shift (>>>)
  • yield*
  • Block statement
  • continue
  • export
  • for...in
  • if...else
  • let
  • try...catch
  • with Deprecated
  • get
  • The arguments object
    1. callee Deprecated
    2. extends
    3. Static initialization blocks
  • Character class escape: \d, \D, \w, \W, \s, \S
  • Input boundary assertion: ^, $
  • Modifier: (?ims-ims:...)
  • Quantifier: *, +, ?, {n}, {n,}, {n,m}
  • Errors
    1. RangeError: argument is not a valid code point
    2. RangeError: invalid array length
    3. RangeError: repeat count must be less than infinity
    4. ReferenceError: assignment to undeclared variable "x"
    5. SyntaxError: 'arguments'/'eval' can't be defined or assigned to in strict mode code
    6. SyntaxError: \ at end of pattern
    7. SyntaxError: await is only valid in async functions, async generators and modules
    8. SyntaxError: continue must be inside loop
    9. SyntaxError: function statement requires a name
    10. SyntaxError: identifier starts immediately after numeric literal
    11. SyntaxError: invalid assignment left-hand side
    12. SyntaxError: invalid class set operation in regular expression
    13. SyntaxError: invalid property name in regular expression
    14. SyntaxError: invalid unicode escape in regular expression
    15. SyntaxError: missing ) after argument list
    16. SyntaxError: missing } after property list
    17. SyntaxError: missing variable name
    18. SyntaxError: numbers out of order in {} quantifier.
    19. SyntaxError: property name __proto__ appears more than once in object literal
    20. SyntaxError: rest parameter may not have a default
    21. SyntaxError: super() is only valid in derived class constructors
    22. SyntaxError: unlabeled break must be inside loop or switch
    23. TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed
    24. TypeError: "x" is not a function
    25. TypeError: BigInt value can't be serialized in JSON
    26. TypeError: can't convert BigInt to number
    27. TypeError: can't redefine non-configurable property "x"
    28. TypeError: class constructors must be invoked with 'new'
    29. TypeError: Initializing an object twice is an error with private fields/methods
    30. TypeError: Iterator/AsyncIterator constructor can't be used directly
    31. TypeError: property "x" is non-configurable and can't be deleted
    32. TypeError: X.prototype.y called on incompatible type
    33. JavaScript technologies overview
    34. Strict mode
    35. Learn more
    36. See full compatibility
  • The switch statement evaluates an 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.

    Try it

    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
    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

    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

    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 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.

    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 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 scopes themselves (neither do they automatically break out — as demonstrated above). For example:

    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 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 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

    Specification
    ECMAScript® 2026 Language Specification
    # sec-switch-statement

    Browser compatibility

    See also