I’d Rather switch Than Fight!

By YUI TeamApril 25th, 2007

JavaScript’s switch statement was inspired by Java’s switch statement, which was inspired by C++’s switch statement, which was inspired by C’s switch statement, which combined aspects of C. A. R. Hoare’s case statement and Fortran’s computed goto statement. Dijkstra considered the goto statement to be harmful, which it in fact is, which is why the goto has been omitted from most modern programming languages. But some of the goto‘s problematic nature survives in the switch, so some extra care must be employed when using it.

The problem with switch was once thought to be its cleverest feature: Fallthru. If you do not explicitly interrupt the flow of control, after executing the code associated with a case, the code of the next case is run too. This provides for a sort of local code reuse, but it can make programs that are harder to read, and it can mask bugs. Accidental fallthru bugs can be very expensive to identify and fix. The best defense against them is to never intentionally use fallthru. That way, if a fallthru ever appears in your code, you can immediately recognize it as a defect that needs correction. That is a lot easier than trying to figure out which fallthrus are accidental and which are not.

Features like fallthru are attractive nuisances. They are sometimes useful, but they encourage weak coding patterns. JavaScript has more than its share of attractive nuisances (with, implied globals, new, and semicolon insertion, to name a few). Your programs will be stronger if you avoid them.

JavaScript’s switch is better than Java’s because it allows matching on strings. This is really useful. The ability to switch on strings satisfies the role that enum provides in other languages. Being able to do more with less is a mark of a good programming language.

JavaScript matches its cases with the === operator, which tests for equality without type coercion. (The == operator does type coercion, which sometimes produces surprising results. It is another attractive nuisance.) The value NaN cannot be found to be equal to itself, so

case NaN:

will never match.

20 Comments

  1. Excellent advice, as always! The trend of competing to produce more and more concise JavaScript expressions is leading to some really abstruse scripts, making their management a nightmare. I would rather spend a couple of cents on bandwidth than a couple of hours deciphering code.

  2. I’m not sure switch fall throughs are evil in and of themselves. They can be quite helpful when used correctly, though I typically encourage people to comment these fall throughs instead of leaving others guessing:

    switch(value){
    case 0:
    doSomething();
    /*falls through*/
    case 1:
    doSomethingElse();
    }

  3. I remember seeing switch with fall through in the jsmin code: the action function. Do you now consider that a good or bad use of switch?

    I agree about “with”, semicolon insertion, and implied globals but I have never understood your objection to “new”. What is it that is so difficult with new? I’ve never had a problem with it.

  4. > The == operator does type coercion, which sometimes produces surprising results. It is another attractive nuisance.

    Interesting. Do you do most of your comparisons with the === operator? I usually use it only when I know it will be necessary (e.g. when I need “” and 0 to be different). But I wonder if I would avoid some unnecessary errors by making === my default choice, instead of ==.

  5. I wrote JSMin a few years ago. I think my programming style has improved since then. If I were writing it today, I would not use fallthrus.

    My style has evolved significantly over the years as a result of understanding that most of my programming time is spent in debugging. Anything I can do in coding to reduce debugging is a huge win.

    I don’t use JavaScript’s == and !=. They don’t do what I mean.

  6. [...] Douglas Crockford gibt im Yahoo! Interace Blog eine kleine Lehrstunde in Sachen switch-Statement. switch, geerbt aus einer langen Ahnenreihe von Programmiersprachen (Java, C++, C), kann ein mächtiges Instrument sein. Aber – mächtige Instrumente habe das oft an sich – es ist auch gefährlich: man kann es viel zu sehr zu einem goto umwandeln, was man nicht will. Auch wenn die Erinnerung an alte Brotkastentage lebt: [...]

  7. The readability problem is solved by a // falls through comment. This is not a case of “may be harmful” but rather a personal coding style preference, so I’m glad you represented it as such.

    FWIW, “fallthru” isn’t a word.

  8. It would be interesting to hear more abut why fall through was once considered it’s “clevest feature”. What was the original use case?

  9. [...] I’d Rather switch Than Fight! JavaScript has more than its share of attractive nuisances (with, implied globals, new, and semicolon insertion, to name a few). Your programs will be stronger if you avoid them. COBOL’s GOTO (with the implied EXIT) is trouble too! (tags: JavaScript Programming) Share and Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages. [...]

  10. The point is that you must actively do something to stop a fall-through. That’s why it causes bugs. If the switch were designed differently, where you needed to include a continue or some other keyword in order to turn on fall-through, then the only times when a fall-through would happen is when the programmer intended it to happen. In the end, avoiding most bugs is all about aligning the code semantics with programmer intent. (It’s not like we’re dumb. We know what we’re trying to do, in most cases.)

  11. The case you list is very useful and not bug-prone. It’s when there are lines of code but no break in between cases that things can get really tricky. Some languages (I’m pretty sure C# and Java do this) allow for your case while disallowing the general, tricky case.

  12. As an old Fortan guy, let me put in a good word for GOTO. Forgetting for a second that it’s just a branch statement, and that no matter the language all loop and if/switch/case/whatever statements get compiled down to branches, sometimes jumping out of hairy nested constructs is easier to figure out with a GOTO than with a series of labeled break statements. (Whether the code should be refactored to eliminate the hairy nest is another issue altogether.)

    However, a computed GOTO really is evil.

  13. johnnysaucepn said:
    April 30, 2007 at 1:25 am

    Whether the code should be refactored to eliminate the hairy nest is another issue altogether.

    Actually, it’s the same issue! GOTO is evil because it allows you to get away with hairy coding, and makes it even hairier. I’m no fan of switch/break/fallthrough, but at least the break doesn’t have to specify where to go next – all breaks go to the same place.

  14. GOTO is evil because it allows you to get away with hairy coding

    The hairy code I’m talking about is not something that’s “gotten away with,” but a result of an evolutionary process, of years of modification by a multitude of programmers given a myriad of requirements under many time constraints. You know, the real world.

    And I compared GOTO to labeled breaks, which don’t all go to the same place.

  15. Since the fallthru is the exception rather then the rule, the ‘break’ in each case should be assumed and a ‘fallthru’ command used to explicitly break the rule (no pun intended). However it is dificult to retrospectively correct for poor design.

  16. I always thought there was something fishy about that switch statement…I always felt dirty using it and never exactly could put my finger on it.

  17. I actually liked goto. It made looping easy in QBasic. Doesn’t ActionScript also have the notion of goto?

  18. What if the “break” statement was on the same line as “case.” Would that make it more obvious?

    switch(arg) {
    case “”:

    break; case “”:

    break; case “”:

    break; case “”:

    case “”:

    break; case “”:
    }

  19. Ted, I’m not sure about fall through being switch’s “cleverest feature”, but it could be a reference to Duff’s device.

    JavaScript saw fit to change switch (compared to the C version) by not allowing the case statements to be embedded in interior statements (as in Duff’s device), but mysteriously didn’t take to opportunity to remove fall through. Strange.

    switch in JavaScript has another “attractive nuisance” too (love the term). You can have non constant expressions in the case labels. Happily I seem to be the only one to have noticed that.

  20. Martijn Laarman said:
    March 13, 2008 at 9:33 am

    I only use switch’s fallthrough for grouping

    switch(i)
    {
    case 3:
    case 6:
    dosomething()
    break;
    case 1:
    case 4:
    doSomethingElse();
    break;
    default:
    doSomethingElseAllTogether()
    }

    In such cases the fallthrough is easy to pick up and very a sementical solution.

    When 3 needs to do somethingOdd() and doSomething() and 6 only needs to doSomething() i generally avoid, and thus agree with the artice, the usage of switch.