Why we REALLY need to stop using switch statements in JavaScript
By: Dor Nisim
Tags: Objects, JavaScript, Switch, Functional Programming, Design Patterns

For example, let’s create a function that returns the result of a binary operation between two numbers, according to an operation string given to the function.

doAction(4, 5, "+") // returns 9

doAction(2, 3, "-") // returns -1

doAction(-1, 5, "*") // return -5

doAction(10, 2, "/") // return 5

doAction(3, 0, "/") // Throws an Exception due to division by zero

If we use an if-else structure, the function will be written as follows

function doAction(a, b, operation){

let result;

if(operation === "+"){

result = a+b;

}

else if(operation === "-"){

result = a-b;

}

else if(operation === "*"){

result = a*b;

}

else if(operation === "/"){

if(b === 0){

throw new Error("Can't divide a number by 0");

}

result = a / b;

}

else{

result = undefined;

}

return result;

}

As one may notice, the code is cluttered and involves many if-else statements which all focus on determining the value of the parameter operation .

For such cases (which are surprisingly common), the switch statement was created, to relieve us from this cluttered mess.

function doAction(a, b, operation){

let result;

switch(operation){

case "+": result = a + b;

break;

case "-": result = a - b;

break;

case "*": result = a * b;

break;

case "/": if(b === 0){

throw new Error("Can't divide a number by 0");

}

result = a / b;

break;

default: result = undefined;

}

return result;

}

Today, thanks to Javascript’s objects and functional programming concepts, we can transform most switch statements to an object.



The code above will be changed as follows

const doAction = (function(){

const functionsObject = {

"+" : (a, b) => a+b,

"-" : (a, b) => a-b,

"*" : (a, b) => a*b,

"/" : (a, b) => {

if(b === 0){

throw new Error("Can't divide a number by 0");

}

return a / b;

}

};

return function (a, b, operation){

let resultFunction = functionsObject[operation];

if(resultFunction){

return resultFunction(a,b);

}

};

})()

Not only that we got a function that still works the same, we have a clear separation between logic and value parsing.

So why do we need to stop using the switch statement?

In order to demonstrate this, we will focus on the following problem.



Alice and Bob are enjoying a game of Rock, Paper and Scissors.

Our task is to write a function that evaluates a single game between Alice and Bob and outputs the winner of the game.



Let’s examine several solutions to this problem, and show why the use of the switch statement isn’t as helpful as once has been considered.

Solution 1: Switch structure

In this solution, we will use the switch structure.

function Switch_RPS_Eval_Game(alice, bob) {

// If Alice and Bob chose the same choice, we will output a tie

if (alice === bob) {

console.log("Alice and Bob tie")

}

else {

let isAliceWin; // variable to determine if Alice won

// Switch on Alice choice

switch (alice) {

case "Rock": switch (bob) {

case "Scissors": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Scissors": switch (bob) {

case "Paper": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Paper": switch (bob) {

case "Rock": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

}

if (isAliceWin) {

console.log("Alice Wins!");

}

else {

console.log("Bob Wins!");

}

}

}

In order to know who the winner is, we first determine Alice’s selection with a switch statement , and then determine Bob’s selection with another switch statement.

One can notice that the function (though short) still looks a bit cluttered.

Solution 2: Object structure

Let’s create an object, similar to the switch structure, with keys that determine the possible selections.

The value of each key, will be another object that contains only the selections that will lead to a win.

const RPS_rules = {

Rock: { Scissors: true },

Scissors: { Paper: true },

Paper: { Rock: true }

};

Now we will use the object to construct a function that given an object (in the structure described earlier) will return a new function.

The new function will receive Alice’s and Bob’s selections and output who the winner is.

function createRuleGame(rulesObj) {

return function (alice, bob) {

// If Alice and Bob chose the same choice, we will output a tie

if (alice === bob) {

console.log("Alice and Bob tie")

}

else {

// variable to determine if alice won

let isAliceWin = rulesObj[alice][bob];

if (isAliceWin) {

console.log("Alice Wins!");

}

else {

console.log("Bob Wins!");

}

}

}

}

Finally, we can build the desired function!

const Object_RPS_Eval_Game = createRuleGame(RPS_rules);

That’s it!

This is the whole function!

Notice how we don’t have the clutter of the case, default and break statements that was previously added to the code.

Switch_RPS_Eval_Game("Rock", "Paper"); // Bob Wins!

Object_RPS_Eval_Game("Rock", "Paper"); // Bob Wins!

So why do we REALLY need to stop using the switch statement?

After a long afternoon of playing Rock, Paper and Scissors, Alice and Bob wanted to play something more exciting and decided to play Rock, Paper, Scissors, Lizard, Spock.

Rock, Paper, Scissors, Lizard, Spock is a game, invented by Sam Kass and Karen Bryla, that extends the Rock, Paper and Scissors game.

The rules of the game are as follows.

Scissors cuts Paper

Paper covers Rock

Rock crushes Lizard

Lizard poisons Spock

Spock smashes Scissors

Scissors decapitates Lizard

Lizard eats Paper

Paper disproves Spock

Spock vaporizes Rock

(and as it always has) Rock crushes scissors

Below is a graphical representation

A diagram of the game’s rules. (from The Big Bang Theory Wiki | Fandom)

Once again, our task is to write a function that evaluates a single game between Alice and Bob and outputs the winner of the game.

Solution 1: Switch structure (The REALLY messy solution)

Since we can’t “extend” the function we created earlier, we are left with no other choice but to create an entirely new function.

function Switch_RPSLS_Eval_Game(alice, bob) {

// If Alice and Bob chose the same choice, we will output a tie

if (alice === bob) {

console.log("Alice and Bob tie")

}

else {

let isAliceWin; // variable to determine if alice won

// Switch on Alice choice

switch (alice) {

case "Rock": switch (bob) {

case "Lizard":

case "Scissors": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Scissors": switch (bob) {

case "Lizard":

case "Paper": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Paper": switch (bob) {

case "Spock":

case "Rock": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Lizard": switch (bob) {

case "Paper":

case "Spock": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

case "Spock": switch (bob) {

case "Rock":

case "Scissors": isAliceWin = true;

break;

default: isAliceWin = false;

}

break;

}

if (isAliceWin) {

console.log("Alice Wins!");

}

else {

console.log("Bob Wins!");

}

}

}

Not only we had to duplicate the code from the previous function, this function is more cluttered, harder to read and difficult to maintain.

Solution 2: Object structure (The cleaner solution)

Thanks to the previous function we created earlier ( createRuleGame ), all we need to do is to create a new object with the game’s “rules” and use it.

const RPSLS_rules = {

Rock: {

Scissors: true,

Lizard: true

},

Scissors: {

Paper: true,

Lizard: true

},

Paper: {

Rock: true,

Spock: true

},

Lizard: {

Paper: true,

Spock: true

},

Spock: {

Scissors: true,

Rock: true

}

};

And the desired function is created as follows

const Object_RPSLS_Eval_Game = createRueGame(RPSLS_rules);

Mind Blowing!

Switch_RPSLS_Eval_Game("Lizard", "Paper"); // Alice Wins!

Object_RPSLS_Eval_Game("Lizard", "Paper"); // Alice Wins!

The bottom line

It will be a long way until the switch statement will be deprecated, but it doesn’t mean that we still have to use it.



By leveraging the power of Objects and Functional Programming concepts in Javascript (and other programming languages), we can create a cleaner, readable and easy to maintain codebase



So, if you still have some “ugly” switch statements in your code, don’t be afraid to give it the makeover it deserves!