DEV Community ๐ฉโ๐ป๐จโ๐ป

Sumudu Siriwardana

Posted on • Updated on

If-Else or Switch-Case: Which One to Pick?

In case you are wondering, Dasha is a conversational-AI-as-a-service platform that lets you embed realistic voice and text conversational capabilities into your apps or products. Start building for free!

If you are a newbie to programming and JavaScript, you might be confused about which conditional statements to use, especially between if-else and switch-case statements.

When I first learned about conditional statements, I thought it was simple enough, and I could use either if-else or switch in any case. But then, when I learned more about this topic and tried to apply it to some problems, I got confused about which one I should use, what's the exact difference, and how I should choose the correct one.

I struggled over understanding the difference and application of these two conditional statements and dug deeper into the topic.

In this article, I will explain these two concepts and provide a comparison chart, so you will understand how you can use if-else and switch-case in different scenarios according to the complexity.

Before jumping into details, let's refresh our memory on why we use conditional statements in our programs.

As human beings, we make various decisions all the time that affect our lives. For example, if we have some free time, we have to decide what to do, whether to rest, watch something, call someone or maybe do something productive.

Conditional statements allow us to make such decisions based on a condition in JavaScript. If the condition is true, we can perform one action, otherwise, we can perform a different action.

So if-else and switch-case both allow us to make these decisions based on a condition. If you want to refresh your memory on how the conditional works, check out this MDN article.

The if-else and else-if statements

As newbies, we all love if-else statements! ๐

If-else statement takes a specific condition and checks whether the condition is truthy or falsy. If the condition is true, then the `if` statement executes a specific code block. If the condition is false, then the `else` statement executes a different code block.

Let's take a simple example to understand how this works.

Scenario One

Imagine that you are the class teacher for grade 5, class C. You have to check students' grades based on their marks, and you only have to check whether the student has passed or failed. Let's check one of the student's grades based on their marks using an if-else statement.

``````function studentGrade(marks) {
if (marks >= 50) {
return "You have passed the exam! ๐ฅณ";
} else {
return "You have failed the exam!";
}
}

console.log(studentGrade(75)); // "You have passed the exam! ๐ฅณ"
``````

According to the above example, we have written a simple function that takes student marks and checks whether it's above 50 or below 50. If the marks entered are 50 or above, then the `if` block executes. If it's below 50, then the `else` block executes.

Scenario Two

Now, imagine taking a step further and giving the result based on the students' specific grades. For example, if the student gets an "A+", the student receives "Nailed It! ๐ฅณ". If the student gets a "D", the result would be "Failed ๐ข".

To have multiple choices like this, we can use the else-if statements to chain the extra choices.

See below code written according to the second scenario with else-if statements.

``````function studentFinalResultIf(grade) {
return "Nailed It! ๐ฅณ";
} else if (grade === "A") {
return "Passed ๐";
} else if (grade === "B+") {
return "Passed ๐";
} else if (grade === "B") {
return "Passed ๐";
} else if (grade === "C") {
return "Barely Survived ๐";
} else if (grade === "D") {
return "Failed ๐ข";
} else {
return "Failed ๐ข";
}
}

cconsole.log(studentFinalResultIf("A+"));   // "Nailed It! ๐ฅณ"
``````

According to the above function, we use different conditional statements to provide students' results depending on the grade. Except for the first code block, which is the `if` block, all the other conditions are tested in `else if` blocks. And if none of the conditions are true, the last `else` executes its code block.

Switch statements

The switch statement is a multiple-choice selection statement. Once you have given the choices and relevant expressions for each choice, It looks through the choices until it finds the choice that matches the expression and executes it.

Let's rewrite the second scenario using the switch statement.

``````function studentFinalResultSwitch(grade) {
case "A+":
return "Nailed It! ๐ฅณ";
case "A":
case "B+":
case "B":
return "Passed ๐";
case "C":
return "Barely Survived ๐";
case "D":
return "Failed ๐ข";
default:
return "Failed ๐ข";
}
}

console.log(studentFinalResultSwitch("A+"));   // "Nailed It! ๐ฅณ"
``````

In the above example, we have the main condition that has many choices. When we check the specific grade, it checks which expression the grade belongs to and then runs that case block. In this case, when the grade is an "A+", it runs `case "A+":` and returns the result "Nailed It! ๐ฅณ".

Now you might be thinking both if-else and switch statements are pretty much alike, and maybe if-else seem more straightforward to use. And you might have your reasons for choosing one over the other. So before jumping to any conclusions, let's check the differences between if-else and switch statements.

Comparison Chart

Basic Terms If-else Switch-case
Check the testing expression An if-else statement can test expression based on a range of values or conditions. A switch statement tests expressions based only on a single integer, enumerated value, or string object.
Ideal for if-else conditional branches are great for variable conditions that result into Boolean. Switch statements are ideal for fixed data values.
Creation of jump table In the if-else case, we do not create a jump table, and all cases are executed at runtime. In switch case, we create jump table on compiled time only selected case is executed on runtime.
Type of search If else implements linear search. Switch implements binary switch.
Condition & expression Having different conditions is possible. We can only have one expression.
Evaluation If-else statement evaluates integer, character, pointer or floating-point type or Boolean type. Switch statement evaluates only character or integer value.
Sequence of execution It is either if-statement will be executed, or else-statement is executed. Switch case statement executes one case after another till a break statement appears or until the end of the switch statement is reached.
Default execution If the condition inside if statements are false, then by default, the else statement is executed if created. If the condition inside switch statements does not match with any of the cases, for that instance, the default statement is executed if created.
Values Values are based on the constraint. Values are based on user choice.
Use It is used to evaluate a condition to be true or false. It is used to test multiple values of the same variable or expression like 1, 2, 3, etc.
Editing It is difficult to edit the if-else statement if the nested if-else statement is used It is easy to edit switch cases as they are recognized easily.

According to the above comparison, you can see the decision of which conditional statement to choose is depending on the scenario and its complexity. For example, we can select both if-else and switch statements for the second scenario since we are just checking one report, which might not make any difference in performance except readability.

Let's take a step further and make our scenario a little bit complicated.

Scenario Three

What if we want to print grades for all the students in all classes? Imagine that we have ten classes for grade 5. And each class includes 50 students. So altogether, we have to check and print the results for around 500 students.

If we use the if-else statement for this, we might run into a slight performance delay. It's because, during the execution, the if-else statement always executes the expression to check whether the condition is satisfied or not. Things would get slower when there are more conditions to check and when the choices get complex.

On the other hand, a switch statement works comparatively faster because the compiler generates a jump table for switch-cases during compile time. So when the code runs, instead of checking which cases are satisfied, it only decides which cases should be executed. In our third scenario, to generate reports for many students, the switch-case might be the better approach.

I hope now you can understand that based on the above comparison and our examples, both statements have their place in the code and it's up to you to choose which one suits which scenario. There is no right or wrong way of doing it.

So how can we choose which statement to use?

Choosing one over the other is not that straightforward. Here are some tips when choosing one over the other;

You can use if-else when:

• The condition result is a `boolean`.
• The conditions are complex. For example, you have conditions with multiple logical operators.

You can use a switch-case when:

• There are multiple choices for an expression.
• The condition is based on a predefined set of values such as enums, constants, known types. For example, error codes, statuses, states, object types, etc.

So based on performance, readability, understandability, changeability, you would have to decide whether to use if-else statements or switch statements. When you read more code and write more code, eventually, you will start figuring out which one is suitable for which scenario; it comes with practice.

Also, there are more approaches if you want to avoid the conditionals as much as you can, especially in JavaScript; array lookup or object lookup are a couple of common approaches.

Closing thoughts

You might find it confusing to decide when to use which statement as a newbie, but it gets better with more practice. Remember that every case requires a specific solution but there's no right or wrong answer. And it's up to you to choose a suitable solution based on your experience. So I hope that the comparison provided here makes it easier for you to identify the difference between if-else and switch statements and not pick one side.

If the only tool you have is a hammer, you tend to see every problem as a nail - Abraham Maslow

Happy coding!

References:

Join Dasha Developer Community where youโll meet welcoming like-minded developers who share ideas, questions, and get all the help they need to build cool conversational AI apps (for free, of course).

Jon Randy ๐๏ธ • Edited on

You can also use switch like this:

``````switch(true) {
case x==1:
// code block
break;
case y==3:
// code block
break;
case z / 5 >= 3:
// code block
break;
default:
// code block
}
``````

Sumudu Siriwardana

Yes, thank you for mentioning that. But I've heard that having "true" is not the best practice of writing it. But I definitely have to do more research on this and understand why.

๐ฉWii ๐๐๐๐๐๐๐ • Edited on

Because jump-tables go out the window when your cases aren't constants. Other languages (Looking at you, C) don't even allow this in the first place.

If you ask me, this is not a good reason to avoid using this feature; but one should be aware that it won't be optimised the way you could with constant expressions*.

* Although, a really smart JIT-Compiler might figure out that an expression is constant for a specific closure (or trace, if it's a tracing JIT) and optimise it into a jump table. Don't think any JIT would bother with such a specific optimisation, but it is an option.

Riccardo Bernardini • Edited on

A good reason to avoid this construct is readability: the typical "switch" construction is turned upside-down with a constant as "controlling value" and non-constant cases. ...and this flip gets you... nothing?

It is interesting as study case, as "look what you can do" but I cannot see a reason (read: a real advantage) to use it in a real case and the disorientation that causes to the reader is a big disadvantage.

Jon Randy ๐๏ธ • Edited on

Don't see why not. It can make some convoluted blocks of `if`s easier to read if you ask me. Nothing odd going on - `switch` just compares the value of one expression with the values of the expressions listed as the cases. We can match any expressions that are `true`.

It's probably not considered 'best' practice as it doesn't adhere to the irrational dogma of the high priests of 'clean' code

Mike Ekkel

There's literally no need for the last sentence of your comment.

As to why it's considered not a best practice: while you could definitely use a screwdriver as a hammer, that's not the intended use. It's an incredibly smart way of using the `switch` statement but it's not the way it's intended to be used and as such is harder for people to understand.

Jon Randy ๐๏ธ • Edited on

If we continually write code catering to the lowest common denominator of understanding, developers will never learn all about how the languages really work - denying them the chance to improve their knowledge.

I'm a firm believer in increasing real understanding of languages. We should never tell developers they 'must' do this, that, or the other - rather, we should let them learn real understanding of how stuff works... and then - armed with that knowledge they can decide how best they can utilise the language.

Showing them something that challenges their understanding of a language feature can only benefit them, by gaining a fuller understanding

Mike Ekkel

This isn't about catering to the lowest common denominator, though. This is about writing clever code that has no reason being clever. It doesn't add to a person's understanding of how the language works because, like I said, it's telling someone to use a screwdriver as a hammer. The entire premise of the `switch` statement is to compare the expression to the cases.

Your code works, I'm not arguing that, just like you could easily hammer away at a nail using a screw driver but at what cost?

Jon Randy ๐๏ธ • Edited on

The entire premise of the switch statement is to compare the expression to the cases.

Which is precisely what my example is doing. Yes, it looks different to most examples of switch statements, but it's really no different - just comparing expression with expression

Conan

Gentleman gentleman, there is a third way.

(I hope you don't find the self-promoted library distasteful - I link to others at the bottom of this very short article, and of course reference the TC39 spec for pattern-matching.)

By the way, I've found that even though `switch (true) { ... }` not so common, the reaction I usually see from those learning it for the first time is "Oh wow, you can do that?". There's just not a lot of friction to understanding it.

xtofl • Edited on

The entire premise of the switch statement is to compare the expression to the cases.

Which is precisely what my example is doing.

... for certain interpretations of 'precisely': `switch(true) { case f(x): ...}` is effectively, undeniably comparing `true` to a number of predicates.

It is effectively, undeniably not comparing a value unknown at design time to one of several, distinct, possibilities, all known at design time.

Proper understanding of the language would lead to the realization that this is the opposite of what `switch` is intended for.

When any developer, whatever their programming language, sees a `switch`, they will rightfully expect an enumeration of non-overlapping cases. This assumption allows them to effectively communicate intent.

Their surprise will lead to misunderstandings, lost time, bugs, everything the one paying for the code does not want.

We should distinguish 'understanding of languages' and 'understanding what the runtime makes of it'. If we mix these up, the latter interpretation would give us carte blanche to use whatever makes the program work and blame our colleagues for not 'understanding the inner workings'. I happily refer to Duff's device and isqrt for some examples of where this leads to; justified in some cases, but to be shunned in general.

`switch(true)` does not belong in production code. I will refuse to merge a pull request containing it.

Of course, every language needs poetry. So allow me to step out of my dogmatic production-code mindset, and appreciate the reversal of the intended use as an form of art.

Conan

When any developer, whatever their programming language, sees a switch, they will rightfully expect an enumeration of non-overlapping cases. This assumption allows them to effectively communicate intent.

I'm not convinced that intent is so clearly carried by syntax and convention alone. Surrounding context counts for a lot, and can make or break the understanding of any chunk of isolated code. I think it's perfectly reasonable to permit out-of-usual syntax so long as you can see what's going on when zooming out a bit.

I'm also not too sure that the two C/C++ examples you gave are germane. JS doesn't have proper pointers, let alone the ability to abuse them for type-casting. It can't have interleaved syntax either. `switch (true)`, fall-throughs, and omitting `default:` are all naturally permitted by the spec.

If you don't like them, drop an `eslint` rule and they won't even make it into a PR. Incidentally, I wonder if a marvel like `InvSqrt` would even exist if we had linters back then? ๐ค

Jon Randy ๐๏ธ • Edited on

Yup, I'm a hoot in code-reviews... luckily, I'm normally leading them. Just call me Leonardo of the PR

xtofl

Totally agree: syntax alone won't convey all your intent. Like a calligrapher can still write absolute nonsense. The point was that `switch(true)...` actively hides the intent.

xtofl

Now that, I can appreciate: the great artist-inventor's role is to experiment with the know rules (hey someone has to do it!) and build interesting and beautiful devices, some adopted right away, others understood only after 400 years :).

Chris Howard

Big fan of this method. I know it's an anathema to the purists... but if my language allows it, then they don't have a problem, so I'll use it.

Luke Shiru

One thing I do quite often is when I have a bunch of values that will return other vales, it feels like a "map", so instead of something like this:

``````function studentFinalResultIf(grade) {
return "Nailed It! ๐ฅณ";
} else if (grade === "A") {
return "Passed ๐";
} else if (grade === "B+") {
return "Passed ๐";
} else if (grade === "B") {
return "Passed ๐";
} else if (grade === "C") {
return "Barely Survived ๐";
} else if (grade === "D") {
return "Failed ๐ข";
} else {
return "Failed ๐ข";
}
}
``````

I have stuff like this:

``````const studentFinalResultIf = grade =>
({
"A+": "Nailed It! ๐ฅณ",
A: "Passed ๐",
"B+": "Passed ๐",
B: "Passed ๐",
C: "Barely Survived ๐",
D: "Failed ๐ข",
``````

And for the `if` example, similarly if I only return one thing or other based on a given value, I just user a ternary:

``````const studentGrade = marks =>
marks >= 50 ? "You have passed the exam! ๐ฅณ" : "You have failed the exam!";
``````

Cheers!

๐ฉWii ๐๐๐๐๐๐๐

In the if-else case, we do not create a jump table, and all cases are executed at runtime.

This is not necessarily true; compilers may still optimise if-statements into jump-tables if they're simple enough. Whether any compiler bothers doing this is another question, of course.

Also, another option is to build your own jump-tables. In JavaScript, these are called "objects" ๐

wait what is `===` and `==` and `=` in js
three equal to sign is very confusing

Jon Randy ๐๏ธ

`=` is assignment
`==` is equality (no type checking)
`===` is strict equality (type checking)

My explanation here is greatly simplified - the rules for equality when using `==` are quite complex

Riccardo Bernardini

the rules for equality when using == are quite complex

Alas, that is one of the worst sin of JavaScript. == is not even transitive, which is a basic property that you would expect from equality. It is not just an academic matter, some algorithms (e.g., sorting) make the implicit hypothesis that equality is transitive and they can break down if it is not. The reason why we do not observe many break downs is that in sorting procedures data are of the same type and this "feature" of JS == (but also PHP has the same problem) does not manifest itself.

Comment deleted

Riccardo Bernardini

I do not have the possibility of checking it, but if I remember correctly

``````"1.200" == "1.2"
``````

is true because since both sides "look" like floating point numbers, they are converted both to float before doing the comparison.

``````console.log('1.200' == '1.2'); // false
console.log(1.2 == '1.2'); // true
console.log('1.200' == 1.2); // true
``````

MDN: Equality (==) โ Comparison with type conversion

• If the operands are of different types, try to convert them to the same type before comparing:
• When comparing a number to a string, try to convert the string to a numeric value.
• If one of the operands is a boolean, convert the boolean operand to `1` if it is `true` and `+0` if it is `false`.
• If one of the operands is an object and the other is a number or a string, try to convert the object to a primitive using the object's `valueOf()` and `toString()` methods.

Sumudu Siriwardana

Jon has explained it very simply!

dev.to/sumusiriwardana/beginners-g...

When in doubt โ use functions.

``````const topResult = (next) => (grade) =>

const midGrades = new Set(['A', 'B+', 'B']);
const midResult = (next) => (grade) =>

const lowResult = (next) => (grade) =>

const failResult = (_grade) => 'Failed ๐ข';

const studentFinalResult = topResult(midResult(lowResult(failResult)));

console.log(studentFinalResult('A+')); // "Nailed It! ๐ฅณ
``````

๐

MDN: Closures

Tania Rascia

This is uniquely terrible. It's so much less readable than either an if/else or a switch.

peerreynders

This is uniquely terrible.

Chain of Responsibility sends its regards.

Riccardo Bernardini

A side note from a different language...

In Ada you can use `switch .. case` (actually it is `case .. when` like in Ruby) only with discrete types: integers and enumerations. The nice part of the `case` in Ada is that you are obligated to specify all the cases. It can seem like a burden, but it saved me from many bugs that would had happened because I forgot to update a `case` after adding a new item to an enumeration type.

Of course there is the "default" case (`when other`), but I try to avoid it since it "disables" the safety check that all the cases are specified.

What about when you do a `case` with an integer? You cannot, of course, specify all the integers... Well, in that case you can use the `when other` (it is legit, after all), but often is better to define a new integer type with explicit bounds.

peerreynders

TypeScript supports exhaustiveness checking on union types.

``````type Grade = 'A+' | 'A' | 'B+' | 'B' | 'C' | 'D' | 'F';

case 'A+':
return 'Nailed It! ๐ฅณ';
case 'A':
case 'B+':
case 'B':
return 'Passed ๐';
case 'C':
return 'Barely Survived ๐';
case 'D':
case 'F':
return 'Failed ๐ข';
default:
const _exhaustiveCheck: never = grade; // "Type 'string' is not assignable to type 'never'".
return _exhaustiveCheck;               // if one of the union type values is missing
}
}

console.log(studentFinalResult('A+')); // "Nailed It! ๐ฅณ"
``````

playground

Tania Rascia

If you can turn an if/else into a switch, it's probably better as an object.

``````const NAILED_IT = "Nailed It! :partying_face:";
const PASSED = "Passed :dancer:";
const BARELY_SURVIVED = "Barely Survived :relieved:";
const FAILED = "Failed :cry:";

'A+': NAILED_IT,
'A': PASSED,
'B+': PASSED,
'B': PASSED,
'C': BARELY_SURVIVED,
'D': FAILED,
'F': FAILED
}