Switch Cases Do Not Have To Be Static In JavaScript
In ColdFusion, Switch Cases have to be static. Meaning, the value of a Case statement has to be hard-coded within the source code. Having been a ColdFusion developer for a long time, I just assumed that this is how it worked in other languages as well - I figured it was some sort of compile-time / optimization requirement. But, this morning, I just realized that this is not the case in JavaScript (no pun intended). In JavaScript, switch cases can be dynamic values.
To test this for myself (and I even went back and tested this on IE7 to make sure I wasn't crazy), I created a simple page that would log the value of variable based on both static and dynamic case values:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>
Switch Cases Do Not Have To Be Static In JavaScript
</title>
</head>
<body>
<h1>
Switch Cases Do Not Have To Be Static In JavaScript
</h1>
<script type="text/javascript">
var userInput = "foo";
// --------------------------------------------------------------------------- //
// --------------------------------------------------------------------------- //
// In this version, our CASE values are going to be static, hard-coded values.
switch ( userInput ) {
case "foo":
console.log( "User entered 'Foo'." );
break;
case "bar":
console.log( "User entered 'Bar'." );
break;
case "baz":
console.log( "User entered 'Baz'." );
break;
}
// --------------------------------------------------------------------------- //
// --------------------------------------------------------------------------- //
// In this version, our CASE values are going to be dynamic variables that will
// be evaluated, on the fly, as the runtime moves down the list.
var INPUT_FOO = "foo";
var INPUT_BAR = "bar";
var INPUT_BAZ = "baz";
switch ( userInput ) {
case INPUT_FOO:
console.log( "User entered 'Foo'." );
break;
case INPUT_BAR:
console.log( "User entered 'Bar'." );
break;
case INPUT_BAZ:
console.log( "User entered 'Baz'." );
break;
}
// SIDE NOTE: In ColdFusion, this approach to Switch / Case statements would
// error with the following: "This expression must have a constant value."
</script>
</body>
</html>
As you can see, in the first switch block, the case values are hard-coded. And, in the second switch block, the values are based on dynamic variables. When we run this code, we get the following console output:
User entered 'Foo'.
User entered 'Foo'.
Holy cow! This kind of blew my mind. It's scary to think that I misunderstood such a fundamental feature of the JavaScript language; and, for so many years! I guess it's never too later to learn.
Want to use code from this post? Check out the license.
Reader Comments
When you use switch (true), you can use different if-statements as case:
<pre>
function test() {
console.log('test');
return true;
}
switch (true) {
case test():
console.log('foo');
break;
default:
console.log('default');
break;
}
</pre>
This logs 'test' and 'foo' to the console.
Haha, great one. I've used this in the past but it's been so long that I had forgotten about it.
@Robert,
That's pretty crazy that you can use a Function *call* as the "case" value. JavaScript - you so dynamic :D
@Mike,
I'm just always shocked that I keep learning these little things. For a language has a relatively small syntax, it seems to always surprise me :D
Just FYI, Ben... Railo and Lucee both handle dynamic case values no worries. It's just ColdFusion that can't manage it.
A quick repro case here: https://github.com/adamcameron/cfml/blob/master/language/statements/flowControl/switch/dynamicCaseInScriptWithFunction.cfm
--
Adam
Ben,
I'm not working in ColdFusion anymore, so I can't check, but I wonder if CFScript (as opposed to CFML) can handle dynamic cases. I wouldn't be surprised either way.
@Ted,
I double-checked this morning on Adobe ColdFusion 10 with CFScript - still a no-go.
@Adam,
Ah, good to know. I do think that multiple case statements can *look* much nicer than if/else-if statements, especially when they are switching on a single value. In the past, I've had to fallback to if/else-if because of the limitation. Good to know it's way more prevalent than I realized.
Pardon me but did you mean final or constant variables? I don't think static is correct in this context. The static keyword means that something (a field, method or nested class) is related to the type rather than any particular instance of the type.
@Edward: a better description would perhaps be a *constant value*. And the only way to express a constant value in CFML is with a literal. It also, as far as I can tell, must be a simple literal.
@Adam... Ya... Java has the same constraints on lambda expressions ... the variables have to be 'final or effectively final' ~ immutable.
@Adam, @Edward,
You guys talk like you think I have any idea what I'm talking about most of the time :P I know very little about the terminology of actual computer science. What I meant was that the CASE value had to be a "literal" maybe? I am not sure what the correct term would be.
@Ben... :) NP ... I hope I didn't come across as a critique man... I was just confused by the 'static' reference... I believe you were trying to express was an immutable variable, which, has a final, constant value ~ "This expression must have a constant value." ~ sorry for the long wind ;)
@EricElliot has a pretty awesome post on immutability in JavaScript I'm thinking you'd really dig... ;)
https://medium.com/javascript-scene/the-dao-of-immutability-9f91a70c88cd
@Edward,
No offense taken at all :) I wish I knew more about correct terminology.
I'll take a look at Eric's stuff. His articles are always quality.
@Ben... I learned a lot of terminology when studying Java... In most statically typed langauges you're required to understand modifiers... dynamic langs dont really necessitate that.
"never too later to learn"
@Edward,
All I know is that I used to try to sub-class certain ColdFusion classes, but they are all flagged as "Final" so you can't mess with them :)
Good to know, Ben. BTW, I'm still coding in CF and, like the Godfather, just when I thought I was out, they -- and lots of posts that refer back to BenNadel.com -- keep pulling me back to your blog!
@Evil Ben,
Ha ha ha, I'm gonna write you a blog post you can't refuse :D
You scared me there for a bit. I thought i missed that you can dynamically insert case statements to a switch.
@Emir,
Ha ha, that would be interesting. Though, I have seen approaches like that were people use a hash instead of a set of case statements. Like, they will use something like:
commands.foo = function(){ ... };
commands.bar = function(){ ... };
commands.baz = function(){ ... };
... And then, instead of a switch/case paradigm they will do something like:
commands[ switchValue ].call( ... )
With that kind of approach, you could dynamically add "case" statements by adding new keys to the hash.