why does this simple switch statement always run the default - javascript

Ok guys, It seems like this switch statement is forever doomed to NOT work.
The initial idea was to create a variable x which is a prompt, the user will have to select enter any number and that would be the value of x.
Then under the first case of the switch, if x is less than 0.5 then it will simply console.log "less".
If x is more than 0.5 it will simply console.log "more".
If for some reason the program didn't work as expected the default is to console.log "this is the default"
Then i added a console.log of x in the end just to know what number did the user enter.
Lets try it!
I tried and tried and regardless of what number i enter it always printed "this is the default". Then printed the value of x.
I ended up going Rambo and removing the prompt and declaring x to be 0.6. It ought to print "more" but it still doesn't.
var x = 0.6;
switch (x) {
case x < 0.5:
console.log("less");
break;
case x > 0.5:
console.log("more");
break;
default:
console.log("its the dflt");
};
console.log(x);
So I'm wondering whats wrong with this code. Help

switch compares what you switch with against the cases. So, if you have case x < 0.5: which you want to run, that case will run if the expression you switched against was true:
var x = 0.6;
switch (true) {
case x < 0.5:
console.log("less");
break;
case x > 0.5:
console.log("more");
break;
default:
console.log("its the dflt");
};
console.log(x);
If you switch against x itself, a case will only run if the case evaluates to the same value as x, which, here, is 0.6, eg:
var x = 0.6;
switch (x) {
case 0.6:
console.log('x is exactly 0.6');
break;
default:
console.log("x is something other than 0.6");
};
console.log(x);
But that's not flexible at all, and isn't what you want.
Personally, I'd prefer if/else, it's a lot easier to read (and, as some points out in comments, is a lot faster):
var x = 0.6;
if (x < 0.5) {
console.log("less");
} else if (x > 0.5) {
console.log("more");
} else {
console.log('neither less nor more; equal or NaN');
}

Switch compares the value of x to the value of the cases. In your code x < 0.5 evaluates to true. Instead of going to that case like if-statements, the switch case compares x and true. Since x is a number, x will never equal true so the default case is always taken.
I would use if-statements instead of a switch in this instance. Switches are better for enumerations (checking if x is a specific value out of a set of values, not a range of values)

CertainPerformance has answered you question very well however if you still don't understand how to use switch I would recommend you use "if statements" until you have the time to read more on using switch.
var x = 0.6;
if (x < 0.5) {
console.log("less");
}
else if (x > 0.5) {
console.log("more");
}
else {
console.log("its the dflt");
}
console.log(x);
Hope this is easier for you :)

Related

How to correctly write a condition in switch? [duplicate]

This question already has answers here:
javascript switch(true)
(5 answers)
Closed 5 years ago.
Good afternoon!
Why does the first option work - switch (true), and the second option does not work - switch (a)?
First:
var a= prompt('Enter value', '');
switch(true)
{
case a>10:
alert('a>10');
break;
case a<10:
alert('a<10');
break;
default:
alert('a===10');
Second:
var a= prompt('Enter value', '');
switch(a)
{
case a>10:
alert('a>10');
break;
case a<10:
alert('a<10');
break;
default:
alert('a===10');
Why does the first option work - switch (true), and the second option
does not work - switch (a)?
As per documentation
The switch statement evaluates an expression, matching the
expression's value to a case clause, and executes statements
associated with that case.
So, in your first option true will match to either a < 10 or a > 10, however in second option, a being a string may not match to either of them.
Edit: I just realize OP ask for the difference instead of why it won't work, sorry for misunderstanding the question
It should work nicely
var a = prompt('Enter value', '');
switch (true) {
case (a > 10):
alert("a > 10");
break;
case (a < 10):
alert("a < 10");
break;
default:
alert('a == 10');
}
It's because a > 10 is true, like the switch(true), while switch(a) was passed a, which is not true. Of course, you should cast a. a = +a or use parseInt() or parseFloat().
Here's what you probably meant to do:
var a = prompt('Enter value');
if(+a > 10){
alert('a > 10');
}
else if(a !== '' && +a < 10){
alert('a < 10');
}
else if(+a === 10){
alert('a === 10');
}
else{
alert('Really, you should avoid using prompt and alert!');
}
// notice this is less code than that pointless switch
You need to convert the user input from a string to an integer, like so
a = parseInt(a)

Switch statement compare user input Javascript

I'm trying this simple code and seems like the user's input is not going through all the comparisons and jumps to the default one right away. I'm guessing that JS is taking the user's input as a string instead. I did try to parseInt() but didn't work. Here is my code;
var number = prompt('What\'s your favority number?');
switch(number){
case (number < 10):
console.log('Your number is to small.');
break;
case (number < 100):
console.log('At least you\'re in the double digits.');
break;
case (number < 1000):
console.log('Looks like you\'re in three digits.');
break;
default:
console.log('Looks like you\'re in the fouth digits.');
}
Use true as an expression for switch.
The switch statement evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.[Ref]
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 strict comparison, ===) and transfers control to that clause, executing the associated statements. (If multiple cases match the provided value, the first case that matches is selected, even if the cases are not equal to each other.) . If no matching case clause is found, the program looks for the optional default clause, and if found, transfers control to that clause, executing the associated statements.
var number = prompt('What\'s your favority number?');
number = Number(number); //Use `Number` to cast it as a number
switch (true) {
//----^^^^
case (number < 10):
console.log('Your number is to small.');
break;
case (number < 100):
console.log('At least you\'re in the double digits.');
break;
case (number < 1000):
console.log('Looks like you\'re in three digits.');
break;
default:
console.log('Looks like you\'re in the fouth digits.');
}
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
Edit: As suggested by #bergi in the comments, an if/else cascade is the best approach for this problem.
var number = prompt('What\'s your favority number?');
number = Number(number); //Use `Number` to cast it as a number
if (number < 10)
console.log('Your number is to small.');
else if (number < 100)
console.log('At least you\'re in the double digits.');
else if (number < 1000)
console.log('Looks like you\'re in three digits.');
else
console.log('Looks like you\'re in the fouth digits.');
You're not understanding how the switch statement works. It is not a shortcut for checking dynamic values. It's a shortcut for checking known values.
Each case is a statement that gets evaluated to a value. If you look at the docs, you'll see that they have case: value, rather than what you are attempting, which is case: (expression). So, it's going to turn all your expressions into values.
So, for example, your first case is:
case (number < 10):
But what that really becomes is:
case false:
And of course, no number will evaluate to false (technically 0 is a falsey value, but the switch uses === comparison rather than == so 0 === false // false). Thus, all your cases are really case false, and so the switch is falling through all of them and landing on the default case.
So, for your situation, the switch statement is inappropriate. You should use if statements.
if(number < 10) {
} else if(number < 100) {
} else if(number < 1000) {
} else {
}
The switch statement is only appropriate when you know the values:
switch(number) {
case 10:
break;
case 100:
break;
case 1000:
break;
default:
}
(And yes, use parseInt to ensure you have integers.)

Is "eval" the only way to use JS "switch" as an expression?

I found that in JavaScript, switch is always a sentence of instruction and using it as an expression will give an error.
So when I have to assign different values to a variable according to different condition, I have to write like this:
switch(true){
case x<0.1: aVariable = '#f0f0f0';break;
case x<0.2: aVariable = '#d3eadf';break;
case x<0.3: aVariable = '#bce1cd';break;
case x>=0.3: aVariable = '#9cd4b9';break;
}
Or I should use 'eval()' like this:
aVariable = eval("switch(true){"+
"case x<0.1:'#f0f0f0';break;"+
"case x<0.2:'#d3eadf';break;"+
"case x<0.3:'#bce1cd';break;"+
"case x>=0.3:'#9cd4b9';break;"+
"}");
Is there any other way to use switch as an expression rather than a sentence of instruction so that I can make my code less verbose?
An alternative is to use a function and invoke it immediately:
var aVariable = (function(){ switch(true){
case x<0.1: return '#f0f0f0';
case x<0.2: return '#d3eadf';
case x<0.3: return '#bce1cd';
case x>=0.3: return '#9cd4b9';
}})(); // call it immediately
You can also do this trick with ifs since return short circuits:
var aVariable = (function(){
if (x < 0.1) return '#f0f0f0';
if (x < 0.2) return '#d3eadf';
if (x < 0.3) return '#bce1cd';
if (x >= 0.3) return '#9cd4b9';
})(); // call it immediately
Basically, the trick is that we're wrapping it in a function expression which converts it into an expression, this technique of an immediately invoked function expression is a useful trick in JavaScript.
You can use a direct approach with an array and calculate the index when you have values with fixed interval. So according to your values, you need
value index comment
----- ----- ------------------------------------------
0.0 0 take integer of value * 10
0.05 0 see above
0.1 1 see above
0.15 1 see above
0.2 2 see above
0.25 2 see above
0.3 3 see above
0.35 3 covert by condition and a fixed value of 3
0.40 3 see above
This answer may not look good for four values, but when it comes to more values with fixed intervals, than it is easier to think about an other structure of decision logic.
function color(x) {
return ['#f0f0f0', '#d3eadf', '#bce1cd', '#9cd4b9'][x > 0.3 ? 3 : x * 10 | 0];
}
var i;
for (i = 0; i < 0.5; i += 0.05) {
document.write(i.toFixed(4) + ' ' + color(i) + '<br>');
}
This is not a very good use of switch. The switch (true) trick is generally frowned upon. If you do choose to use it, and you do want it to "return" a value, then yes, you could wrap it in an anonymous function. What a lot of extra machinery! Why not just write
x < 0.1 ? '#f0f0f0' :
x < 0.2 ? '#d3eadf' :
x < 0.3 ? '#bce1cd' :
'#9cd4b9'
This is not to say there are not valid use-cases for wanting a statement or block to return a value, and there have been animated discussion on the ES Discuss group about this very topic. I'm just saying this is not really one of those cases.
In addition to the roundabout methods described in other answers, "switch expression" will be achievable when either of the two JS proposals materialize:
pattern matching
do-expressions

Numeric comparison failure in a switch statement

"original post" : This function should compare the value of 'a' with several other values, but always defaults. My test shows that the value of 'a' or 'b' is never changed. Do I have the case a > statement incorrect or elsewhere?
Now I understand that I can not use comparison in the case statement:
Should I use a bunch of if statements and a while (a <> = 0) to do the multiple checking and decrementing?
The snippit below shows 'a' with a particular value. In the full function, actually 'a' gets a value from a random number in another function. It must be checked against 16 possible values and decremented, then rechecked until it finally reaches 0. The comparison values are actually powers of 2 (1 through 16).
function solution() {
var a = 18000;
var b = 0;
switch (a) {
case a > 30000:
a = a - 30000;
b = b++;
break;
case a > 16000:
b = b++; a = a - 16000;
break;
case a > 8000:
b = b++; a = a - 8000;
break;
default:
c = "defaulted!, Why?";
break;
}
window.alert (a + " " + b + " " + c);
}
Don't use switch for range checks like this. It's possible with
switch (true) {
case (a > 30000):
a = a - 30000;
b = b++;
but just don't do that.
Use if/else instead. While switch is really just an abstract if/else construct, use it for things like this:
switch(a){
case 1: ...
}
In a nutshell, you can't use boolean expressions in switch case labels. You'll need to rewrite the code as a series of if statements.

jquery Using ranges in switch cases?

Switch cases are usually like
Monday:
Tuesday:
Wednesday:
etc.
I would like to use ranges.
from 1-12:
from 13-19:
from 20-21:
from 22-30:
Is it possible? I'm using javascript/jquery by the way.
you could try abusing the switch fall through behaviour
var x = 5;
switch (x) {
case 1: case 2: case 3: case 4: ...
break;
case 13: case 14: case 15: ...
break;
...
}
which is very verbose
or you could try this
function checkRange(x, n, m) {
if (x >= n && x <= m) { return x; }
else { return !x; }
}
var x = 5;
switch (x) {
case checkRange(x, 1, 12):
//do something
break;
case checkRange(x, 13, 19):
...
}
this gets you the behaviour you would like. The reason i return !x in the else of checkRange is to prevent the problem of when you pass undefined into the switch statement. if your function returns undefined (as jdk's example does) and you pass undefined into the switch, then the first case will be executed. !x is guaranteed to not equal x under any test of equality, which is how the switch statement chooses which case to execute.
Late to the party, but upon searching for an answer to the same question, I came across this thread. Currently I actually use a switch, but a different way. For example:
switch(true) {
case (x >= 1 && x <= 12):
//do some stuff
break;
case (x >= 13 && x <= 19):
//do some other stuff
break;
default:
//do default stuff
break;
}
I find this a lot easier to read than a bunch of IF statements.
You can make interesting kludges. For example, to test a number against a range using a JavaScript switch, a custom function can be written. Basically have the function test a give n value and return it if it's in range. Otherwise returned undefined or some other dummy value.
<script>
// Custom Checking Function..
function inRangeInclusive(start, end, value) {
if (value <= end && value >= start)
return value; // return given value
return undefined;
}
// CODE TO TEST FUNCTION
var num = 3;
switch(num) {
case undefined:
//do something with this 'special' value returned by the inRangeInclusive(..) fn
break;
case inRangeInclusive(1, 10, num):
alert('in range');
break;
default:
alert('not in range');
break;
}
</script>
This works in Google Chrome. I didn't test other browsers.
Nope, you need to use an if/else if series to do this. JavaScript isn't this fancy. (Not many languages are.)

Categories