【问题标题】:Does a javascript if statement with multiple conditions test all of them?具有多个条件的 javascript if 语句是否会测试所有条件?
【发布时间】:2010-12-28 04:19:13
【问题描述】:

在 javascript 中,当使用带有多个条件的 if 语句进行测试时,javascript 是否会测试所有条件,或者如果它已经为假,它会在测试所有条件之前放弃吗?

例如:

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

javascript 会测试所有这 3 个条件,还是在看到 b 不等于 1 并因此为假之后,它会退出语句吗?

我是从性能的角度来问的。例如,如果我正在测试 3 个复杂的 jQuery 选择器,我宁愿不要让 jQuery 遍历 DOM 3 次,如果通过第一个选择器很明显它会返回 FALSE。 (在这种情况下,嵌套 3 个 if 语句会更有意义)。

附录:更多的是好奇,这个的正确术语是什么?我注意到你们中的许多人使用“短路”一词。另外,有些语言会这样做而其他语言不会吗?

【问题讨论】:

  • @Josh:我完全理解这是微优化的想法。很高兴知道。也就是说,如果一个选项比另一个选项更优化,我认为了解并养成使用所述方法的习惯是件好事。 (另外,我也很好奇答案)
  • 严格来说,这不是一个过早的优化。在具有短路逻辑的语言中,重要的是要知道在什么条件下某些方法不会被执行;例如,如果您依赖它们的副作用。
  • 这里还有一个关于“短路评估”的问题:stackoverflow.com/questions/1232603/…

标签: javascript


【解决方案1】:

&& 运算符“短路” - 也就是说,如果左侧条件为假,则无需评估右侧条件。

同样,如果左侧条件为真,|| 运算符也会短路。

编辑:不过,在您进行基准测试并确定这是一个问题之前,您不应该担心性能。过早的微优化是可维护性的祸根。

【讨论】:

  • 优秀的答案(技术部分和管理问题)。谢谢!
  • 如果您确实希望它执行布尔语句的所有部分,您可以使用 & 和 |分别为和或
  • 这种情况不一定总是与性能有关。有时您可能会进行空值检查,并说如果您的空值检查是条件 a,然后您尝试执行 a (b == value + 1) 进行第二次检查,如果所有三个条件都已检查,则会出现错误。
  • 确实,短路与性能无关。然而,最初的问题是从性能的角度提出的。
  • 非常好。进行这种微优化(以及其他)可能会在滚动事件循环中产生很大的影响,例如多个元素的视差计算,甚至是粘性条。举个例子:if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop) 第二个条件是一个更昂贵的计算,第一个只是一个布尔值。 :)
【解决方案2】:

从性能的角度来看,这不是微优化。

如果我们有 3 个布尔变量,a、b、c,那就是微优化。

如果我们调用 3 个返回布尔变量的函数,每个函数都可能需要很长时间,而且不仅要知道短路,而且要知道短路的顺序。例如:

if (takesSeconds() && takesMinutes())

好很多
if (takesMinutes() && takesSeconds())

如果两者返回 false 的可能性相同。

【讨论】:

    【解决方案3】:

    这就是为什么你可以用像

    这样的 javascript 代码来做
    var x = x || 2;
    

    这意味着如果 x 未定义或为“假”,则默认值为 2。

    【讨论】:

    • 即使 JS 不支持短路评估,这也可以工作。
    • 这相当于三元吗?
    【解决方案4】:

    如果有人想知道是否有办法强制评估所有条件,在某些情况下可以使用位运算符&|

    var testOr = true | alert(""); //alert pops up
    var testAnd = false & alert(""); //alert pops up
    

    这些应该非常小心地使用,因为位运算符是算术运算符,只在其操作数的单个位上工作,不能总是充当&& 和@ 的“非短路”版本987654326@

    示例:

    -2147483648 && 1 = 1 
    

    但是

    -2147483648 & 1 = 0
    

    希望它可以帮助到达这里的人(像我一样)寻找这样的信息,并感谢@Max 的更正和反例

    【讨论】:

    • 这个答案是错误的。 & 和 |是按位运算符,它们不是“&& 和 || 的非短路版本”。位运算符是在其操作数的单个位上工作的算术运算符。示例:-2147483648 && 1 = 1 但 -2147483648 & 1 = 0。更多信息:en.wikipedia.org/wiki/Bitwise_operation
    • @Max 实际上我不知道这一点,自从我学习 C 以来,我一直在使用它(我现在称之为“技巧”)。幸运的是,这些输入永远不会破坏我的代码上来了。我纠正了我的答案,我欠你的
    • @DJDaveMark 抱歉,我无法让您的 false && (alert("")) 解决方案正常工作:/
    • @ivcandela 我也不能。如果我不在手机上,我会第一次测试它;o) 可惜你不能编辑 cmets。我刚刚删除了它并在下面添加了另一个
    • 强制评估的更简单更好的方法是将结果保存在变量中,然后针对变量进行测试,即:var a=false; var b=check(); alert(a && b);
    【解决方案5】:

    如果第一个条件为真,它只会测试所有条件,你自己测试一下:

    javascript: alert (false && alert("A") && false);
    

    【讨论】:

      【解决方案6】:

      它短路 - 在您的示例中仅比较 a 和 b。

      【讨论】:

        【解决方案7】:

        使用左侧 1 个或多个参数停止评估的另一个原因。

        if (response.authResponse && (response.authResponse.accessToken != user.accessToken)){ ... }

        第二次评估依赖于第一次为真,如果 response.authResponse 为 null 或 undefined 等,则不会抛出编译错误,因为第一个条件失败。

        其他语言在早期就有这个问题,我认为这是现在构建编译器的标准方法。

        【讨论】:

          【解决方案8】:

          看到 b 不等于 1 后退出。

          【讨论】:

            【解决方案9】:

            对于这个问题的任何人都感到困惑,因为他们在使用 ||? 运算符时没有看到短路行为,如下所示:

            x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

            似乎短路规则不起作用。当第一个为真时,为什么要评估 || (true ? 2 : 3) 的第二个词?原来是运算顺序问题,因为上面等价于

            x = (1 || true) ? 2 : 3

            首先评估||,其次评估?。您可能想要的是:

            x = 1 || (true ? 2 : 3)

            【讨论】:

              【解决方案10】:

              对于这种情况:

              a = 1
              b = 2
              c = 1
              
              if (a==1 && b==1 && c==1)
              

              你可以使用:

              if ([a, b, c].every(x => x == 1))
                  // do something if a, b and c are equal to 1.
              

              如果你想知道至少一个是否等于 1,请使用 some() 方法而不是 every():

              if ([a, b, c].some(x => x == 1))
                  // do something if a, b or c is equal to 1.
              

              every() 和 some() 是数组方法。

              【讨论】:

                猜你喜欢
                • 2014-10-20
                • 2023-03-31
                • 1970-01-01
                • 2020-01-15
                • 1970-01-01
                • 1970-01-01
                • 2016-12-13
                • 2019-10-20
                相关资源
                最近更新 更多