有没有更好的方法在JavaScript中编写此开关?

时间:2017-06-05 09:46:16

标签: javascript performance if-statement switch-statement conditional

我有一个switch,其中包含以下条件:

  • 第一个case是三个名称之间的or(ROKA,MOKA和TOKA)。

  • 第二个case是另一个名称(KOKA),但有两个附加条件来显示alert

  • 最后,我还有一些其他条件可以在default区域内查看,因为我无法使用case

这是我的代码:

var myname= 'JOKA';
var dhaba = false;

switch (myname) {
  case ('ROKA'):
  case ('MOKA'):
  case ('TOKA'):
    alert('EEE');
    break;

  case ('KOKA'):
    // This will work as Goto to final default:

    if (condition1 && condition2) {
      alert('FEEE');
      break;
    }

  default:
    if (dhaba && myname != 'ROKA' && myname != 'TOKA') {
      alert('TEEEE');
    } else {
      alert('CHEEE');
    }
}

有没有更好的方法来编写此代码?

2 个答案:

答案 0 :(得分:1)

当您到达default时,myname始终不等于之前检查的值。使用

就足够了
default:
    if (dhaba) {
        alert('TEEEE');
    } else {
        alert('CHEEE');
    }

答案 1 :(得分:1)

我认为switch不是您用例的最佳选择。

另外,正如@NinaScholz指出的那样,myname != 'ROKA' && myname != 'TOKA'将始终为真,否则您将落入第一个case

让我们一步一步地看看重构代码的不同方法:

简化(非切换)代码

编写代码的简单方法和最直接的方法如下:

const myname = 'JOKA';
const dhaba = false;

if ('ROKA' === myname || 'MOKA' === myname || 'TOKA' === myname) {
    alert('EEE');
} else if (myname === 'KOKA' && true && true) {
    alert('FEEE');
} else {
    alert(dhaba ? 'TEEEE' : 'CHEEE');
}

请注意,如何删除冗余检查,并将最后一个if - else块替换为ternary operator

您的代码可能与您提供的示例完全不同,或者它会随着时间的推移而改变。在这种情况下,您可以考虑除上述简化代码之外的其他选项。

使用Array.prototype.indexOf()

从单个变量中检查多个匹配项

但是,您可能需要在第一个if中检查更多元素。在这种情况下,您可以使用ArrayArray.prototype.indexOf()来检查其中是否有任何匹配(如果没有,则会返回-1):

const myname = 'JOKA';
const dhaba = false;

if (['ROKA', 'MOKA', 'TOKA'].indexOf(myname) !== -1) {
    alert('EEE');
} else if (myname === 'KOKA' && true && true) {
    alert('FEEE');
} else {
    alert(dhaba ? 'TEEEE' : 'CHEEE');
}

N输入 - 输出(字符串)对+复数默认值,带开关

您可能还有多个myname值映射到多个alert()参数,因此您可能会想要写下这样的内容:

const myname = 'JOKA';
const dhaba = false;

switch(myname) {
    case 'XXX-1': alert('YYY-1'); break;
    case 'XXX-2': alert('YYY-2'); break;

    ...

    case 'XXX-N': alert('YYY-N'); break;

    default:
        if (myname === 'KOKA' && true && true) {
            alert('FEEE');
        } else {
            alert(dhaba ? 'TEEEE' : 'CHEEE');
        }
}

虽然这很好,实际上,我认为它比在case块中检查其他条件更清晰且更不容易出错,就像在您的示例中所做的那样,并且基于它做了一些事情{ {1}}或者让下一个块执行,我建议你考虑使用对象文字查找。

N输入 - 输出(字符串)对+复杂默认值与对象文字查找

使用它们有多个优点:更好的可读性,更容易调试,可维护性,简洁性(例如,无需添加break)...我认为对您来说最重要的是,因为您添加了在您的问题中标记break,是否更高效。

这是因为performance必须评估每个switch条件,直到f case为止,因此它们的顺序很重要,对象查找只是一个哈希表查找,即,break

考虑到这一点,我们可以像这样重构最后一个例子:

O(1)

N输入 - 输出(字符串)对+单值默认值,带对象文字查找和|| (或)操作员

另请注意,如果默认仅使用const myname = 'JOKA'; const dhaba = false; const output = { 'XXX-1': 'YYY-1', 'XXX-2': 'YYY-2', ... 'XXX-N': 'YYY-N', }[myname]; // Note output will be undefined if there isn't a match, so the first if // will be evaluated to false in that scenario: if (output) { alert(output); } else if (myname === 'KOKA' && true && true) { alert('FEEE'); } else { alert(dhaba ? 'TEEEE' : 'CHEEE'); } 中的其他值,则可以使用简单的if运算符执行此操作:

||

N输入 - 具有对象文字查找的输出(任意代码)对

请注意,您还可以使用const myname = 'JOKA'; const output = { 'XXX-1': 'YYY-1', 'XXX-2': 'YYY-2', ... 'XXX-N': 'YYY-N', }[myname] || 'DEFAULT OUTPUT'; alert(output); functions为对象中的每个案例执行任意代码:

arrow functions

请注意,您可以在对象声明之上声明那些const myname = 'JOKA'; const output = { 'XXX-1': () => { /* Do something... */ }, 'XXX-2': () => { /* Do something... */ }, ... 'XXX-N': () => { /* Do something... */ }, }[myname](); ... ,并在应该具有相同行为的多个键之间共享它们:

functions

有关使用对象文字查找替换const myname = 'JOKA'; const f1 = () => { /* Do something 1... */ }; const output = { 'XXX-1': f1, 'XXX-2': f1, ... 'XXX-N': () => { /* Do something... */ }, }[myname](); ... 的更多信息,请查看以下帖子:https://toddmotto.com/deprecating-the-switch-statement-for-object-literals