I'm trying to create a switch statement but I can't seem to be able to use an expression that gets evaluated (rather than a set string/integer). I can easily do this with if statements but case should hopefully be faster.
I'm trying the following
function reward(amount) { var $reward = $("#reward"); switch (amount) { case (amount >= 7500 && amount < 10000): $reward.text("Play Station 3"); break; case (amount >= 10000 && amount < 15000): $reward.text("XBOX 360"); break; case (amount >= 15000): $reward.text("iMac"); break; default: $reward.text("No reward"); break; } }
Am i missing something obvious or is this not possible? Google hasn't been friendly in this case.
Any help/pointers appreciated
M
The expression in the switch can be a variable or an expression - but it must be an integer or a character. You can have any number of cases however there should not be any duplicates. Switch statements can also be nested within each other.
The result of a switch expression is the value of the expression of the first switch expression arm whose pattern matches the input expression and whose case guard, if present, evaluates to true . The switch expression arms are evaluated in text order.
The switch statement evaluates an expression. The value of the expression is then compared with the values of each case in the structure. If there is a match, the associated block of code is executed. The switch statement is often used together with a break or a default keyword (or both).
The value of the expressions in a switch-case statement must be an ordinal type i.e. integer, char, short, long, etc. Float and double are not allowed.
amount
is a number, but the expressions in the case
clauses only evaluate to booleans; the values will never match.
You could always do
switch (true) { case (amount >= 7500 && amount < 10000): // Code break; case (amount >= 10000 && amount < 15000): // Code break; // etc. }
It works because the value being matched is now the boolean true
, so the code under the first case
clause with an expression that evaluates to true
will be executed.
It’s kinda “tricky”, I guess, but I see nothing wrong with using it. A simple if
–else
statement would probably be more concise, and you’d not have to worry about accidental fall-through. But there it is anyway.
@MooGoo's switch (true)
will give you a Weird condition
error in jsLint, so let's get a little more creative in case that's an issue, and, I think, increase readability a touch.
So we're not evaluating if each case
is true
or false
; we're comparing if that case
's value is equal to our switch
term. So let's take advantage of that by throwing a shorthand if
into our case
statement and return our original switch term if the condition's true.
I'm also including a sort of real world example, where you want to have two "defaults" -- one if your term is outside of your "important" range in the positive direction, and another in case you're in the negative direction.
Key phrase: case (x > 0 ? x : null):
"If my term, x
, is greater than zero, return x
so that x === x
and I take the case branch."
http://jsfiddle.net/rufwork/upGH6/1/
/*global document*/ /*jslint evil:true*/ var x = 10; switch (x) { case (x > 0 ? x : null): document.write('ha ha ha! I fooled switch AND jsLint! Muhahahahaha!'); break; case 0: document.write('zero is nothing.'); break; case -1: document.write('low'); break; case -2: document.write('lower'); break; case -3: document.write('lowest I care about'); break; default: // anything lower than -3. document.write('TOO LOW!!!! (unless you cheated and didn\'t use an int)'); } document.write('<br>done.');
Do notice that the default:
switch says, "unless you cheated and didn't use an int" and that short circuiting requires x === x
when you return x
.
But your point is a useful reminder that NaN
is the only case where short circuiting can't apply.
That is, x
must == x
to short circuit in switch
and, as MDN tells us, "NaN, and only NaN, will compare unequal to itself" (double or triple =
).
That also means that switching on a NaN
value (and only a NaN
value) will always hit default
in ANY switch
because you can't match its value.
Here's the full quote from MDN:
NaN compares unequal (via ==, !=, ===, and !==) to any other value -- including to another NaN value. Use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN. Or perform a self-comparison: NaN, and only NaN, will compare unequal to itself.
You could change the default
logic to check what you have:
isNaN(x) ? document.write ('nan') : document.write('TOO LOW!!!! ...)');
Or you even could go full hipster like MDN suggests (but please don't ;^D):
x !== x ? document.write ('nan') : document.write('TOO LOW!!!! ...)');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With