为什么在使用 Switch 时需要 Break?

IT技术 javascript switch-statement
2021-03-07 06:30:59

我已经阅读了很多关于 SO 的答案,但似乎无法找到明确的答案,为什么如果在这种情况下省略了 break,则案例“C”将始终被评估为真,而填充的新数组只会“G” ”的。我清楚地明白,最好在这里使用 break,因为我只想评估特定的匹配,而不是为了如果确实省略了 break,为什么最后一种情况总是正确的。

 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);
  })
3个回答

来自 MDN

如果找到匹配项,程序将执行相关的语句。如果多个 case 与提供的值匹配,则选择第一个匹配的 case,即使这些 case 彼此不相等。

与每个 case 标签相关联的可选 break 语句确保程序在执行匹配的语句后中断 switch 并在 switch 之后的语句处继续执行。如果省略了 break,程序将在 switch 语句中的下一个语句继续执行。

所以关于Switch的基本历史是它起源于C,是分支表的抽象,分支表也有隐含的fall-through,需要额外的跳转指令来避免。此外,所有其他语言都继承 switch 作为默认 C 开关语义,主要选择保留默认的 C 语义。因此,在您的 switch 中,如果在所有情况下都省略了 break,则如果找到匹配项,程序将继续执行下一条语句。找到匹配项后,它不会从 switch 退出,而是评估匹配案例下方的所有其他案例,因为解析器认为案例已组合,因为它们之间没有中断为了清楚地解释这种行为,我稍微修改了你的代码。如果A 中断被省略。

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);
})

所以你的输出会像

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

在第一次迭代中,匹配将用于案例A

outArr={'T'}

同样,由于没有break语句,它会将 Case C视为同一块并在那里继续执行。现在

outArr={'G'}

类似地,在第二次迭代中,它与 case T匹配,但有一个break语句,因此控件跳出 switch 并且 outarr 现在将是

outArr={'G','A'}

同样,对于其他迭代,您将获得上面发布的整个输出。

在这里更新了 Bin

是否有您想省略break? 看起来省略breaks 只会导致错误行为,那么为什么该关键字是可选的?
2021-05-06 06:30:59
是的,在某些情况下您可能想要省略break. 检查developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-05-19 06:30:59

当一个 case 匹配时,如果你不中断,它会继续下一个 case,不管它是否匹配条件。所以他们都会遇到最后一个案例,输出将被“G”覆盖

switch并且if/else在某种程度上可以互换,除了break开关中允许的确切内容if/elseif/elseif/..../else链中,只有一个块会被执行,例如

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
}

相比之下,使用 a switch,一旦匹配,就不再进行进一步的比较测试,并且将执行以下所有代码,直到 switch 块关闭 ( }) 或break遇到 a :

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();
}

注意缺少一个breakcase 7行了。这意味着继续执行,并忽略所有其他case行。这意味着do_something()执行,然后other_stuff()执行,然后foo()执行。最后break遇到 a ,它终止了现在长期运行的case,然后继续执行switch.