【问题标题】:Javascript switch vs. if...else if...elseJavascript 切换与 if...else if...else
【发布时间】:2011-02-24 18:17:23
【问题描述】:

各位,我有几个问题:

  1. switch 语句和if...else 之间的 JavaScript 性能是否存在差异?
  2. 如果是,为什么?
  3. switchif...else 的行为在浏览器中是否不同? (FireFox、IE、Chrome、Opera、Safari)

问这个问题的原因是,我似乎在 Firefox 中使用大约 1000 个案例的 switch 语句获得了更好的性能。


已编辑 不幸的是,这不是我的代码,Javascript 是从已编译的库在服务器端生成的,我无权访问该代码。生成 javascript 的方法称为

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

注意arrayofvalues 是一个逗号分隔的列表。

它产生的是什么

function [name] (value) {
  if (value == [value from array index x]) {
     [action from array index x]
  }
}

注意:[name] = 传入服务器端函数的名称

现在我更改了要插入到 TextArea 的函数的输出,编写了一些 JavaScript 代码来解析该函数​​,并将其转换为一组 case 语句。

最后我运行了这个函数,它运行良好,但在 IE 和 Firefox 中性能不同。

【问题讨论】:

  • 我会建议一个代码示例来检查什么是最佳的。我的意思是,你问这个肯定是有原因的,对吧?
  • 请发布您的最新动态,因为在我的长期经验中,很少有案例可以说是 100 案例 switch 语句或 100 部分 if/else 系列是好主意。
  • 对不起,不是 100 岁,而是数千个条件
  • 大家,感谢您的意见。但我的问题实际上并不是 if 和 swith 语句之间的区别。它是在语句中运行的代码。 +1 对你们所有人的帮助。很抱歉给您带来不便。有时您只需要与其他人讨论即可找到解决方案。

标签: javascript cross-browser conditional


【解决方案1】:

笼统地回答:

  1. 是的,通常情况下。
  2. See More Info Here
  3. 是的,因为每个都有不同的 JS 处理引擎,但是,在下面的站点上运行测试时,switch 总是在大量迭代中执行 if、elseif。

Test site

【讨论】:

  • 如果您想要了解何时使用哪些条件的 TLDR,这里是指向文章中的一个段的直接链接:oreilly.com/server-administration/excerpts/even-faster-websites/…
  • @Tommy 好文章,感谢分享。但是文章指出,JS 中的 switchif/then 语句之间的性能差异可以忽略不计。文章指出这是由于参差不齐的switch 优化以及不同的 JS 引擎运行方式不同。引用:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
  • 此描述中是否显示了可量化的内容?它读起来像是很多“最佳实践/过早优化”的猜想。它也是 7 年前写的,所以这段时间 javascript 优化发生了巨大变化。在编译语言中,这三个操作之间的性能差异“几乎从来没有足够重要”。不要费心优化不会影响实际性能的东西。优化可读性。
  • @Tommy «See More Info Here» 给出 404,那是什么?
  • @LogicDaemon - IIRC 是一些 oRielly 文本框的链接,该文本框进入了一些深入的 JS 性能考虑/讨论
【解决方案2】:

有时最好都不使用。例如,在“调度”情况下,Javascript 可以让你以完全不同的方式做事:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

通过创建对象来设置多路分支有很多优点。您可以动态添加和删除功能。您可以从数据创建调度表。您可以通过编程方式对其进行检查。您可以使用其他功能构建处理程序。

为了得到一个“案例”的等价物,函数调用会增加开销,但哈希查找的优势(当有很多案例时)为特定键找到函数。

【讨论】:

  • 你的策略很好,我经常使用它。但正如@Michael Geary stackoverflow.com/a/45336805/5936119 所指出的,map 变量必须在调度上下文之外声明,否则它将始终被重新评估。
  • @DanielSantana 是的,但我怀疑这非常昂贵。特别是,一旦函数被初始解析,代码本身就不需要重新生成,因为文本是静态的。
【解决方案3】:

switchif...else if...else 之间的性能差异很小,它们基本上做同样的工作。它们之间可能产生影响的一个区别是,要测试的表达式仅在 switch 中评估一次,而对每个 if 进行评估。如果计算表达式的成本很高,那么执行一次当然比执行一百次要快。

这些命令(以及一般的所有脚本)的实现在浏览器之间存在很大差异。相同代码在不同浏览器中的性能差异很大是很常见的。

由于您几乎无法在所有浏览器中对所有代码进行性能测试,因此您应该选择最适合您正在做的事情的代码,并尝试减少完成的工作量,而不是优化完成的方式。

【讨论】:

    【解决方案4】:

    Pointy's answer 建议使用对象文字来替代switchif/else。我也喜欢这种方法,但是每次调用 dispatch 函数时,答案中的代码都会创建一个新的 map 对象:

    function dispatch(funCode) {
      var map = {
        'explode': function() {
          prepExplosive();
          if (flammable()) issueWarning();
          doExplode();
        },
    
        'hibernate': function() {
          if (status() == 'sleeping') return;
          // ... I can't keep making this stuff up
        },
        // ...
      };
    
      var thisFun = map[funCode];
      if (thisFun) thisFun();
    }
    

    如果map 包含大量条目,则会产生大量开销。最好只设置一次action map,然后每次都使用已经创建好的map,例如:

    var actions = {
        'explode': function() {
            prepExplosive();
            if( flammable() ) issueWarning();
            doExplode();
        },
    
        'hibernate': function() {
            if( status() == 'sleeping' ) return;
            // ... I can't keep making this stuff up
        },
        // ...
    };
    
    function dispatch( name ) {
        var action = actions[name];
        if( action ) action();
    }
    

    【讨论】:

      【解决方案5】:

      除了语法之外,可以使用树来实现开关,使其成为O(log n),而if/else 必须使用O(n) 程序方法来实现。更常见的是,它们都是按程序处理的,唯一的区别是语法,而且这真的很重要——除非你静态地输入 10k 个 if/else 案例?

      【讨论】:

      • 7 年后......我看不出树的实现是如何可能的,除非是在恒定数值大小写值的情况下)。
      • 3.5 年后...@Ed Staub 当然是这里的情况。 Switch 语句使用常量。无论已经是数字还是其他任何东西,都可以枚举它们,因此可以构建一棵树。
      • @trolkotze 虽然常量是最常见的,但 case 子句可以是任何表达式。参见例如stackoverflow.com/questions/3463833/….
      • 哦,我不知道。这在 C 中是不可能的,afaik。那里只允许使用常量表达式。所以我假设它在 JS 中是一样的。
      【解决方案6】:
      1. 如果存在差异,它永远不会大到足以引起注意。
      2. 不适用
      3. 不,它们的功能都相同。

      基本上,使用任何使代码最易读的东西。肯定有一些地方可以使一种或另一种结构变得更清洁、更易读和更易于维护。这比在 JavaScript 代码中节省几纳秒的时间要重要得多。

      【讨论】:

      • 尤其是在 javascript 中,语义和可读性(以及因此的可维护性)胜过 if..elseswitch 之间由独特的浏览器版本计算机硬件和操作系统组合引起的任何本地化性能差异。
      • 我绝对不同意。随着 Web 应用程序变得越来越复杂,这种差异对应用程序来说可能很重要,并且可能会因浏览器而异。
      • 重要的是编写干净、可维护的代码。当出现性能问题时 - 配置文件。然后确定要修复的代码。不要因为假定的性能问题而牺牲可维护性。
      • 'if else if else ...' 是 O(n),而 'switch' 是 O(1) 或 O(log(n))。你怎么能诚实地说差异永远不够大?在 switch 中有一百万个案例(如果生成代码很容易),至少可以说你肯定会注意到它。
      • 我对此投了反对票,因为我认为在回答第一个问题时所做的概括是不正确的。
      【解决方案7】:

      在性能上有区别吗 switch 语句之间的 Javascript 还有一个 if...else if....else?

      我不这么认为,如果您想防止出现多个 if-else 条件,switch 很有用/很短。

      是开关的行为和 if...else if...else 不同 浏览器? (火狐、IE、Chrome、Opera、 野生动物园)

      所有浏览器的行为都是相同的 :)

      【讨论】:

      • switch is useful/short if you want prevent multiple if-else conditions. 是的,先生,很棒的帖子。
      【解决方案8】:
      1. 工作台在某些情况下可能会导致一些非常小的差异,但处理方式无论如何都取决于浏览器,因此不值得打扰
      2. 因为处理方式不同
      3. 如果行为会有所不同,则不能将其称为浏览器

      【讨论】:

        【解决方案9】:

        事实证明,if-else if 一般比 switch 快

        http://jsperf.com/switch-if-else/46

        【讨论】:

        • JS Perf 不再起作用,很遗憾。
        猜你喜欢
        • 1970-01-01
        • 2013-08-10
        • 1970-01-01
        • 2015-05-16
        • 2019-04-09
        • 1970-01-01
        • 2018-09-19
        • 1970-01-01
        相关资源
        最近更新 更多