switch

Execute code when the value of a variable matches the expected value.

Time to read: less than 5 min

Briefly

The control structure switch allows you to execute different blocks of code depending on the value of a variable.

It is similar to if...else, but solves a narrower problem.

How to write

        
          
          switch (variable_name_value_to_compare) {  case value:    // code    break}
          switch (variable_name_value_to_compare) {
  case value:
    // code
    break
}

        
        
          
        
      

In parentheses, the variable whose value is being compared is specified. In curly braces, possible values and the code that needs to be executed are indicated using the keyword case.

An example of greeting a user depending on their status:

        
          
          switch (membershipStatus) {  case 'vip':    // will execute if the variable membershipStatus contains the string 'vip'    console.log('Welcome, your magnificence!')    console.log('we are glad to see you!')    break  case 'diamond':    console.log('Hello, diamond client!')    break  case 'gold':    console.log('Hello, my golden friend!')    break  default:    // will execute if no other case matched    console.log('Hello')    break}
          switch (membershipStatus) {
  case 'vip':
    // will execute if the variable membershipStatus contains the string 'vip'
    console.log('Welcome, your magnificence!')
    console.log('we are glad to see you!')
    break
  case 'diamond':
    console.log('Hello, diamond client!')
    break
  case 'gold':
    console.log('Hello, my golden friend!')
    break
  default:
    // will execute if no other case matched
    console.log('Hello')
    break
}

        
        
          
        
      

How to understand

In programming, it is often necessary to perform different code depending on some condition. Typically, such tasks are solved using the if...else structure.

Among these tasks, there is a special subtype — when you need to look at the value of a variable and execute different code depending on that value. For example, to apply different discounts for clients of different statuses — give the most favorite clients a 25% discount, those with a loyalty card a 10% discount, and give nothing to regular customers.

Such a task can also be solved using if..else:

        
          
          let discountif (memberStatus === 'vip') {  discount = 0.25} else if (memberStatus === 'diamond') {  discount = 0.2} else if (memberStatus === 'gold' || memberStatus === 'silver') {  // discount 10% for gold and silver status users  discount = 0.1} else {  discount = 0}
          let discount
if (memberStatus === 'vip') {
  discount = 0.25
} else if (memberStatus === 'diamond') {
  discount = 0.2
} else if (memberStatus === 'gold' || memberStatus === 'silver') {
  // discount 10% for gold and silver status users
  discount = 0.1
} else {
  discount = 0
}

        
        
          
        
      

The code above works, but looks excessive — it contains a lot of comparisons using memberStatus. The switch structure solves such a task with less code:

        
          
          let discountswitch (memberStatus) {  case 'vip':    discount = 0.25    break  case 'diamond':    discount = 0.2    break  case 'gold':  case 'silver':    // you can write several cases and link to one block    discount = 0.1    break  default:    discount = 0    break}
          let discount
switch (memberStatus) {
  case 'vip':
    discount = 0.25
    break
  case 'diamond':
    discount = 0.2
    break
  case 'gold':
  case 'silver':
    // you can write several cases and link to one block
    discount = 0.1
    break
  default:
    discount = 0
    break
}

        
        
          
        
      

In parentheses, the variable whose value needs to be compared with various possible values — cases — is specified. The order usually does not matter.

Inside the case, a list of commands that need to be executed is written. The list of commands ends with the break statement.

There is an optional default case that triggers if no value matched.

What happens if you forget to put break?

If you forget to put break, all commands will be executed starting from the triggered case until either a break is encountered or the switch ends.

Compare:

Shows code executed only between the current  and , and code executed from  to , even if it is outside the current case

All code from the current case to the next break will be executed, even if it is outside the current case.

A bug appears in the code — the value for the diamond level will be set to 0.1 instead of 0.2.

In practice

Advice 1

There is a cognitive bias known as “Law of the Instrument”:

If you have only a hammer, everything around you seems like a nail.

So switch often turns into such a hammer. Of course, switch has its advantages: you can use several case at once, you can write different logic in the conditions, and so on.

        
          
          function greet(role) {  switch (role) {    case 'admin':    case 'moder':      return 'Greetings, keeper of order'    case 'user':      trackUserVisit()      return 'Hello, user'    case 'guest':      return 'Hello, guest'    default:      return 'Hello, stranger'  }}
          function greet(role) {
  switch (role) {
    case 'admin':
    case 'moder':
      return 'Greetings, keeper of order'
    case 'user':
      trackUserVisit()
      return 'Hello, user'
    case 'guest':
      return 'Hello, guest'
    default:
      return 'Hello, stranger'
  }
}

        
        
          
        
      

However, often we need to simply match one value to another. And in such cases, it’s better to establish a dictionary:

        
          
          const roleToGreeting = {  admin: 'Greetings, boss',  moder: 'Greetings, keeper of order',  user: 'Hello, user',  guest: 'Hello, guest',}const greetings = (role) => roleToGreeting[role] ?? 'Hello, stranger'
          const roleToGreeting = {
  admin: 'Greetings, boss',
  moder: 'Greetings, keeper of order',
  user: 'Hello, user',
  guest: 'Hello, guest',
}

const greetings = (role) => roleToGreeting[role] ?? 'Hello, stranger'

        
        
          
        
      

There is also the switch (true) pattern, which supposedly shortens if...else if...else:

        
          
          function getCategoryByAge(age) {  switch (true) {    case (age >= 0 && age <= 12):      return "Child"    case (age >= 13 && age <= 19):      return "Teenager"    case (age >= 20 && age <= 35):      return "Young Adult"    case (age >= 36 && age <= 55):      return "Adult"    case (age > 55):      return "Senior"    default:      return "Invalid age"  }}
          function getCategoryByAge(age) {
  switch (true) {
    case (age >= 0 && age <= 12):
      return "Child"
    case (age >= 13 && age <= 19):
      return "Teenager"
    case (age >= 20 && age <= 35):
      return "Young Adult"
    case (age >= 36 && age <= 55):
      return "Adult"
    case (age > 55):
      return "Senior"
    default:
      return "Invalid age"
  }
}

        
        
          
        
      

Using switch (true) is a controversial issue and seems more like a hack rather than an intended usage scenario of the language. Also, keep in mind that this construct may be unfamiliar to your colleagues, unlike ordinary conditions that are clear to everyone. Proponents of switch (true) claim that it allows to shorten the code, but the example above would be more concise without it:

        
          
          function getCategoryByAge(age) {  if (age >= 0 && age <= 12) return "Child"  if (age >= 13 && age <= 19) return "Teenager"  if (age >= 20 && age <= 35) return "Young Adult"  if (age >= 36 && age <= 55) return "Adult"  if (age > 55) return "Senior"  return "Invalid age"}
          function getCategoryByAge(age) {
  if (age >= 0 && age <= 12) return "Child"
  if (age >= 13 && age <= 19) return "Teenager"
  if (age >= 20 && age <= 35) return "Young Adult"
  if (age >= 36 && age <= 55) return "Adult"
  if (age > 55) return "Senior"

  return "Invalid age"
}

        
        
          
        
      

Advice 2

🛠 Make sure to put break at the end of each case. Such code will be easy to read and won't lead to unexpected bugs.

🛠 Always add a default block to your switches. The application code constantly changes. Eventually, the switch will stop covering all possible values of the variable, and the default case will be your safety net that prevents the application from breaking.

🛠 If your switch has fewer than three cases, then if...else will be easier to read.

🛠 If you need to create a variable inside a case, you will have to add curly braces; otherwise, JavaScript will throw an error:

        
          
          switch (variable) {  case 5: {    const myVar = 'Hello'  }}
          switch (variable) {
  case 5: {
    const myVar = 'Hello'
  }
}