javascript switch() or if() - javascript

which would be better if i do this:
if(message == 'redirect')
{
is_valid.accepted = true;
}
else if(message == 'invalid id')
{
is_valid.accepted = false;
}
else
{
is_valid.accepted = false;
}
or i do it this way
switch (message)
{
case 'invalid id':
default:
is_valid.accepted = false;
break;
case 'redirect':
is_valid.accepted = true;
break;
}

You might use switch if you foresaw needing to add lots of new cases.
If you won't be adding many new cases, I might do, for clarity:
is_valid.accepted = message=='redirect';
(also note that your check for 'invalid id' does nothing)
Nevertheless if you had to add new things, notice how it's good you don't have to repeat yourself don't have to repeat yourself don't have to repeat yourself, also the sexy formatting:
switch (message)
{
case 'invalid id':
case 'penguin invasion':
case 'the internet is down':
case 'error not enough caffeine':
is_valid.accepted = false;
break;
case 'redirect':
case 'upvote me':
case 'vip':
case 'flamewar':
is_valid.accepted = true;
break;
default:
is_valid.accepted = false;
// perhaps log or something
}
Imagine all those ugly else and else-ifs you'd have otherwise.
sidenote:
If you had really complicated rules, but still a whitelist-blacklist-on-a-single-flag paradigm, then:
var blacklist = ['invalid id', 'penguin invasion', 'the internet is down' 'error not enough caffeine'];
var whitelist = ['redirect', 'upvote me', 'vip', 'flamewar'];
is_valid.accepted = whitelist.indexOf(message)!=-1;
You might also do this if you wanted to dynamically construct your whitelist.

It depends on your definition of better. Do you want it to be a better reading experience or better performance?
I always jsPerf things. I don't really care much about readability if it makes my code faster/proper.
Here is a jsPerf of a bunch of different switch vs. if/else if/if ==/if === statements.
http://jsperf.com/switch-if-else/16
This is revision 16 of the test. So if you are looking at this 10 weeks from now make sure you scroll to the bottom and grab the most recent test.

The switch statement is more efficient/expressive than if/else in some cases. While the following if/else statement
let x = 123;
if (x) {/*...*/} // implicit type casting (to boolean)
else {/*...*/}
can be easily converted to:
switch (!!x) { // explicit type casting (to boolean)
case true: /*...*/ break;
default: /*...*/
}
this switch statement on the other hand
function algo(x) {/*...performing a complex algorithm...*/}
switch (algo(123)) { // executed once
case "result 1": /*...*/ break;
case "result 2": /*...*/ break;
case "result 3": /*...*/ break;
default: /*...*/
}
results in an incredible inefficient if/else statement (switch is more efficient):
if (algo(123) === "result 1") {/*...*/}
else if (algo(123) === "result 2") {/*...*/}
else if (algo(123) === "result 3") {/*...*/}
else {/*...*/}
or requires an if/else with additional variable, which is declared for this purpose exclusively:
let y = algo(x); // additional variable
if (y === "result 1") {/*...*/}
else if (y === "result 2") {/*...*/}
else if (y === "result 3") {/*...*/}
else {/*...*/}
Please note that additional elements (like variables) cause more complexity and complexity makes programs more error prone. The switch statement doesn't need such a variable, because it is more expressive.

Switch is better if you're working with a long list of possible conditions on the same variable. In this case, I don't think there's much reason to use switch() unless you prefer the syntax.

If you go with the if statement, I personally prefer setting default values above the if, like this:
is_valid.accepted = false;
if(message == 'redirect')
{
is_valid.accepted = true;
}
That way, you always default to a safe behavior that is less likely to break if you add more options later on. Also, you see the default behavior at a glance without having to read through the if-then-else logic. And it's much shorter code.

Ternary?
is_valid.accepted = (message !== 'invalid id') ? true : false;

Related

Javascript switch case that runs code when any case is true?

I have a standard switch case block:
switch(variable) {
case "option1":
alert("Option 1");
break;
case "option2":
alert("Option 2");
break;
}
And I would like to run this code:
alert("Any Option");
Is there a simple way to run this code when either of the cases match, without adding the code to every case, and without rechecking "variable" (i.e. not using an if statement after the switch)?
There are a bunch of really hacky ways to do what you are suggesting (named do loops with break/continue, recursive functions with switch statements, etc.) but the cleanest would be to use a function, like so:
var variable = "option1";
function checkValue (val) {
switch (variable) {
case "option1":
alert("Option 1");
return true;
case "option2":
alert("Option 2");
return true;
default:
return false;
}
}
if (checkValue(variable)) {
// run common code
alert("Any option");
}
A labeled block allows you to break out of it at any time. If you break in the default case, you can run some code following the switch statement when either of the cases match and without rechecking the variable, as requested:
let variable = prompt("option1 or option2?");
select: {
switch(variable) {
case "option1":
alert("Option 1");
break;
case "option2":
alert("Option 2");
break;
default:
break select;
}
alert("Both Options");
}
However, I don't recommend this! Labels make the code execution path less clear. Above code is not readable. Rechecking the variable is a better approach.
Not directly with a switch statement. See The Switch Statement, ECMAScript 2016 standard.
In particular:
Runtime Semantics: Switch Evaluation
Runtime Semantics: CaseBlockExpression
The language spec does not contain the feature that you are looking for.
Why not making a function called by both cases?
switch(variable) {
case "option1":
dualAlert("Option 1");
break;
case "option2":
dualAlert("Option 2");
break;
}
function dualAlert(text){
alert(text);
alert('Common Alert');
}
I don't think i would ever use the pattern you described, nonetheless something like this could suit your needs.
/**
* Use this method to simulate a "finally" statement in a
* method that resembles a switch
*
* #param {*} value - The value to compare
* #param {Array<*, boolean, function>} options - The collection of switch statements
* First value is the value to compare against the original value
* Second value specifies if this statement should behave like a break at its end
* Third value is the action to take when the value matches
* #param {function} finallyFn - The method which is run if any statement was executed
*/
function switchWithFinally(value, options, finallyFn) {
var matched = false,
breakSwitch = true;
for(var i = 0; i < options.length; i++) {
if(!breakSwitch || value === options[i][0]) {
options[i][2]();
matched = true;
breakSwitch = options[i][1];
}
}
if(matched) finallyFn();
}
/**
* Example call, should return
* Option 2
* Option 3
* Any option
*/
switchWithFinally(
'option2',
[
['option1', true, function() {
console.log('Option 1');
}],
['option2', false, function() {
console.log('Option 2');
}],
['option3', true, function() {
console.log('Option 3');
}]
],
function() {
console.log('Any option');
}
);

Switch statement not behaving like it should

so i have a piece of code where i have an array (ar=[1,2,3,4,5]) and two functions. the functions are supposed to do the exact same thing: print out something if 1 exists in the array. but function func is always returning "nope" instead of "one" but function another always return the right thing. the only difference between the two functions is function func have a switch instead of an if/else. why? in the source code there are about 12 cases so i actually need to use the switch.
var ar=[1,2,3,4,5];
function func(num){
var one=num;
switch (one) {
case one===1:
console.log("one");
break;
default:
console.log("nope");
break;
}
}
function another (num) {
if(num===2){
console.log("found two");
} else if(num===3){
console.log("found thre");
} else{
console.log("nope");
}
}
ar.forEach(func);
ar.forEach(another);
You have to use the value you want to compare to one
hence
case 1:
instead of
case one===1
here's a fiddle
https://jsfiddle.net/cunx1ono/
Easiest way. Change the switch param to true if you want to use a comparison in the case, because one===1 returns true/false. This is why you always get "nope".
var ar=[1,2,3,4,5];
function func(num){
var one=num;
switch (true) {
case one===1:
console.log("one");
break;
default:
console.log("nope");
break;
}
}

Unreachable code error when I use a break in my switch statement

I am wondering what I am doing wrong in my code. I am trying to do the following:
switch (action.type) {
case TYPES.ADD_TO_FAVORITES:
if (state.faves.length <= 10) {
return assign({}, state, {
faves: state.faves.concat(action.payload),
full: false
});
} else {
return assign({}, state, {
faves: state.faves,
full: true
});
}
default:
return state;
}
My linter says to add a break before default case, but when I do that, it says unreachable code.
The linter rule i.e. 'no-fallthrough' in eslint, acts as to not allow any accidental fallthrough from case to case.
Meaning without break code execution will continue from matching case to next cases unless a break, return etc is encountered.
Sometimes we do need this but unintentional fallthrough can happen and this rule tries to prevent that.
You can disable the rule or configure it as warning .
I would recommend to have a variable assigned for return value and at the end of the function and return it without disabling the rule.
function() {
var returnvalue;
Switch(variableA) {
Case 1:
returnvalue = somevalue;
break;
case 2:
returnvalue = some other value;
break;
default:
returnvalue= default value;
}
return returnvalue;
}
And for the unreachable part, you are returning from your if else block.
So the break will never get any chance to execute.
switch (action.type) {
case TYPES.ADD_TO_FAVORITES:
if (state.faves.length <= 10) {
return ...;
} else {
return ...;
}
break; // YOU HAVE ADDED BREAK HERE
default:
return state;
}
Inside case TYPES.ADD_TO_FAVORITES, either if or else will be executed. As in both if and else you have returned some object, the break you have added just before default, will never going to be executed!
That's why it says it says unreachable code.
Return in switch statement make no sense and not allowed. You can only return in a function. If you want to get value back from switch statement. Just assign it to a variable like this
var result;
switch (action.type) {
case TYPES.ADD_TO_FAVORITES:
if (state.faves.length <= 10) {
result = assign({}, state, {
faves: state.faves.concat(action.payload),
full: false
});
} else {
result = assign({}, state, {
faves: state.faves,
full: true
});
}
break;
default:
result = state;
break;
}

A switch statement doesn't work when the equivalent if statement does

switch(type)
{
case 'home':
console.log('home switch');
break;
}
The above code does not write out to the console, neither does the following:
switch(type)
{
case "home":
console.log('home switch');
break;
}
The following, however, does:
if (type == 'home')
{
console.log('home if');
}
I don't have a clue why. This isn't a show-stopper, I can use the if statement instead, but I'm genuinely curious as to why this is the case.
NOTE: These statements are a straight replace, nothing else to consider here. No change in scope, no code I'm not mentioning that could be interfering with the value of type.
That's not the equivalent if-statement. The switch statement is specified to use the strict equality === operator.

javascript switch(true)

Hi i am trying to handle an ajax json response
here is my code
success: function (j) {
switch(true)
{
case (j.choice1):
alert("choice2");
break;
case (j.choice2):
alert("choice2");
break;
default:
alert("default");
break;
}
}
based on what j is return i do my action BUT i keep getting the default.
I have alert the j values and come correct.Some how case (j.choice1) case (j.choice2) is not working.
I tried case (j.choice1!="") (j.choice2!="") But in this scenario i keep getting the first choice.
What am i missing
It works for me:
var a = 0, b = true;
switch(true) {
case a:
console.log('a');
break;
case b:
console.log('b');
break;
}
However, the case labels must be equal to true, not just implicitly true.
Also, only the first case that evaluates to true will execute.
SOLVED
Based on SLaks answer i modify the code as below
if(j.choice1){ var choice1=true;} else { var choice1=false;}
if(j.choice2){ var choice2=true;} else { var choice2=false;}
switch(true)
{
case choice1:
alert("choice1");
break;
case choice2:
alert("choice2");
break;
default:
alert("default");
break;
}
For all asking why switch and not if.
Switch will execute only 1 statement, but if can execute more than 1 if any mistake come form response (for example if set choice1 and choice 2 the if will alert both but switch will alert only choice1).
The response expecting as choice has to do with credit card charge to bank so i want to ensure that only 1 action will exetute
Thank to all
You need to read up on the switch statement. You should not be switching on a constant value.
It appears that you need to use if statements, as you don't really want to be switching on your j value:
success: function (j) {
if (j.choice1)
{
alert("choice1");
break;
}
if (j.choice2)
{
alert("choice2");
break;
}
alert("default");
}
}
In a case like this, a better way to do this is probably something like:
success: function (j) {
if(j.choice1 || j.choice2) {
alert("choice2");
} else {
alert("default");
}
}
Why not use an object literal instead of a switch(true) ?
const j= {
choice1: false,
choice2: true
};
const map = {
true: 'default',
...(j.choice1 ? {[`${j.choice1}`]: 'choice1'} :{}),
...(j.choice2 ? {[`${j.choice2}`]: 'choice2'} :{})
}['true']
console.log(map) // 'choice2'

Categories

Resources