9

I've read quite a few answers on SO but can't seem to find a definitive answer as to why if break is omitted in this instance the case "C" will always be evaluated as true and the new array filled will only "G"'s. I clearly understand that break would be best used here as I am only looking to evaluate a specific match but not so as to why the last case is always true if break is indeed omitted.

 var dna = "ATTGC";
 var outArr = [];
 dna.split("").forEach(function(e,i){
    switch(e) {
        case "G": outArr[i] = "C"; break;
        case "T": outArr[i] = "A"; break;
        case "A": outArr[i] = "T"; break;
        case "C": outArr[i] = "G"; break;
    }
    console.log(outArr);
  })
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Joe Keohan
  • 139
  • 1
  • 4
  • 2
    The `switch...case` statement is designed such that if you omit the `break` statement, the evaluation of the condition "falls through" down the various cases. So, what you are seeing when you omit `break` is the condition matching each and every case until the last one. –  Sep 28 '16 at 21:20
  • It's not that the last case is true, rather that each case is an entry point after which all statements will be executed until the end of the `switch` block. – shmosel Sep 28 '16 at 21:29
  • Additional to what jeyoung has commented. The `break;` is there for a good reason, if you want to do same stuff for different cases you can do it and break stops it from happening. – Harshal Carpenter Sep 28 '16 at 21:33
  • 1
    I think the reason you haven't found much on SO about `switch...case` is because it's absolute entry level programming concept that is covered alongside loops and other beginner level materials. It's furthermore cross-language concept since the syntax of `switch` is pretty much exactly the same accross many languages. As such, this question is an exact duplicate of [this Java question](http://stackoverflow.com/questions/2710300/why-do-we-need-break-after-case-statements) - in fact, the question and accepted answer are 100% compatible to JS since they don't use specific Java keywords. – VLAZ Sep 28 '16 at 22:27

3 Answers3

10

From MDN

If a match is found, the program executes 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.

The optional break statement associated with each case label ensures that the program breaks out of switch once the matched statement is executed and continues execution at the statement following switch. If break is omitted, the program continues execution at the next statement in the switch statement.

So the basic history about Switch is it originated from C and is an abstraction of branch table and a branch table also has an implicit fall-through and requires an additional jump instruction to avoid it. Also all other languages inherited switch as default C switch semantics mostly choosing to keep the C semantics per default. So in your switch if break is omitted from all cases, if the match is found program continues execution for next statement. It doesn't exit from switch after the match is found instead it evaluates all other case below the matched case, as parser thinks cases are combined, since there is no break in between them. I have modified your code a bit for clear explanation of this behavior.In case A break is omitted.

var dna = "ATTGC";
var outArr = [];
dna.split("").forEach(function(e,i){
switch(e) {
    case "G": outArr[i] = "C"; break;
    case "T": outArr[i] = "A"; break;
    case "A": outArr[i] = "T";
    case "C": outArr[i] = "G"; break;
}
console.log(outArr);
})

So your Output will be like

["G"]
["G", "A"]
["G", "A", "A"]
["G", "A", "A", "C"]
["G", "A", "A", "C", "G"]

In first iteration match will be for case A.

outArr={'T'}

Again Since there is no break statement, it will consider Case C as same block and continues execution there. Now

outArr={'G'}

Similalrly in second iteration it matches for case T but there is a break statement so controls jumps out of the switch and outarr will now be

outArr={'G','A'}

Similarly for other iterations you will get the whole output as posted above.

Updated Bin here

Community
  • 1
  • 1
breakit
  • 356
  • 2
  • 8
  • 2
    Are there useful cases where you want to omit the `break`? It looks like omitted `break`s can cause only buggy behavior, so why that keyword is optional? – DemX86 Dec 01 '20 at 08:40
  • Yup, there are cases where you might want to omit `break`. Check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch#methods_for_multi-criteria_case –  May 18 '21 at 04:32
3

switch and if/else are somewhat interchangeable, EXCEPT for exactly what break allows for in a switch. In and if/elseif/elseif/..../else chain, only ONE of the blocks will ever execute, e.g.

x = 7;
if (x == 5) {
    ... no match, not executed at all
} else if (x == 7) {
   .... match made, this is executed
} else if (x == 7) {
   ... this will not execute, because the other block already did
} else {
   ... this also never executes, because a match was made earlier
}

In comparison, with a switch, once a match is made, no further comparison tests are done, and ALL code following will be executed, until the switch block closes (}), or a break is encountered:

x = 7;
switch(x) {
    case 5:   ... nothing matched, not executed; break;
    case 7: do_something();
    case 8: other_stuff();
    case 9: foo(); break;
    case 7: ... will not execute, because matching stopped above.
    default: stuff();
}

Note the lack of a break on the case 7 line. That means execution continues, and ignores all further case lines. that means do_something() executes, then other_stuff() executes, and foo() executes. Finally a break is encountered, which terminates this now long-running case, and the execution then proceeds on with whatever comes AFTER the switch.

Marc B
  • 356,200
  • 43
  • 426
  • 500
1

When a case matches, if you don't break, it will continue onto the next case regardless of whether it matches the condition. So they will all hit the last case and the output will be overridden with "G"

Joseph Young
  • 2,758
  • 12
  • 23