【问题标题】:Is there a better way to write this switch in JavaScript?有没有更好的方法来用 JavaScript 编写这个开关?
【发布时间】:2017-11-06 01:24:37
【问题描述】:

我有一个switch,条件如下:

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

  • 第二个 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');
    }
}

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

【问题讨论】:

  • 你可以使用策略模式
  • @Obrit:我不明白它如何适应上述情况。实际上,在这些警报中只有确认框。 dofactory.com/javascript/strategy-design-pattern
  • @fatherazrael 我猜你的意思是 JavaScript 而不是 jQuery,因为 switch 是一个 JavaScript 结构,完全独立于 jQuery。
  • 我在你的代码中没有看到任何 jQuery。
  • @fatherazrael 有人解决了你的问题吗?如果是这样,您能否接受最佳答案(单击点下的复选标记)。这将帮助遇到您的问题的其他用户快速发现接受的答案,并且还提供 15 个代表。指向作者(:

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


【解决方案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 块内的附加条件更干净,更不容易出错,就像您在示例中所做的那样,并在此基础上做一些事情和 break或者让下一个块执行,我建议你考虑使用对象文字查找。

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

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

这是因为虽然switch 必须评估每个case 条件直到找到break,所以它们的顺序很重要,对象查找只是哈希表查找,即O(1)

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

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

? N 输入 - 输出(字符串)对 + 带有对象文字查找的单值默认值 ? 和 || (或)运营商

另外,请注意,如果您的 default 只是在 if 中使用另一个值,您可以使用简单的 || 运算符来做到这一点:

const myname = 'JOKA';

const output = {
    'XXX-1': 'YYY-1',
    'XXX-2': 'YYY-2',

    ...

    'XXX-N': 'YYY-N',
}[myname] || 'DEFAULT OUTPUT';

alert(output);

? N 输入 - 输出(任意代码)对与对象文字查找?

请注意,您还可以使用 functionsarrow functions 为对象中的每个 case 执行任意代码:

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

...

有关用对象字面量查找替换 switchs 的更多信息,请查看此帖子:https://toddmotto.com/deprecating-the-switch-statement-for-object-literals

【讨论】:

    【解决方案2】:

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

    default:
        if (dhaba) {
            alert('TEEEE');
        } else {
            alert('CHEEE');
        }
    

    【讨论】:

    • 不错的收获。 :) 还有什么建议吗?
    • @fatherazrael,其实不是,因为不清楚,你更喜欢做什么。
    猜你喜欢
    • 1970-01-01
    • 2020-03-18
    • 2019-06-15
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多