【问题标题】:JavaScript conditional not short circuiting like I would expectJavaScript 条件不像我期望的那样短路
【发布时间】:2015-01-11 05:06:57
【问题描述】:

我是一位经验丰富的开发人员,但我刚刚遇到了一个问题,我花了一段时间才弄清楚并正在寻找解释。我依赖于短路并且花费了比我愿意承认的调试更多的时间。如果这属于另一个 Stack Exchange 网站,请告知。

我希望以下结果为假,但它通过了:

(false && true || true) => true

好像它被解释为这样:

((false && true) || true) => true

...但解决方案是这样的:

(false && (true || true)) => false

为什么false不短路第一个例子中的操作?是否有某种我不知道的前瞻性?


解决方案摘要:对于那些(像我一样)从不知道条件运算符与数学运算符具有相似优先级的人 - 隐含括号的相同概念适用:

3 * 2 + 1 => (3 * 2) + 1 => 7
false && true || true => (false && true) || true => true

【问题讨论】:

    标签: javascript conditional-statements short-circuiting


    【解决方案1】:

    逻辑与 (&&) 的优先级高于逻辑或 (||)。

    您可以通过添加您在示例中使用的括号来解决问题。

    x && (y || z);
    

    但是,使用显式的 if 语句会更易读:

    if (x && y) {
        z;
    }
    

    Here's a reference chart for operator precedence in JS。 (参见 #13 和 #14。)

    如果您很难理解优先级,请尝试用* 代替&&+ 代替||

    x * y + z;
    

    显然,按照操作顺序,x * y 将首先执行。因此,如果您想先执行y + z,则应使用括号。

    短路与语法无关。这只是布尔运算符的一个怪癖。所以不要这么想

    我一直认为第一个失败的条件会使操作短路,进一步的评估会停止。

    短路不会调用某种退出整个操作的“中止”函数。如果已经可以确定最终结果是什么,那么布尔运算符将忽略它们的第二个参数(a && b 中的b)。 (例如,false && (anything) 始终为 false,因此 && 是惰性的,不会费心评估第二个参数。)

    我仍然不明白false && (anything) 总是假的但false && (anything) || somethingelse 可能是真的。

    好的,所以应用优先规则,我们得到:

    (false && anything) || somethingelse
    

    因此,首先评估 &&。由于它是惰性的,它看到false 并立即返回false

    (false) || somethingelse // `anything' is not evaluated
    

    现在轮到|| 进行评估了。它看到&& 刚刚返回的false,它不能短路,因为false || true 仍然可能是真的。所以它必须评估somethingelse才能得到最终结果。

    因此,代码if((false && anything) || somethingelse)本质上等同于if (somethingelse)

    【讨论】:

    • 感谢您的快速回复。我的真实代码使用 if 语句和业务逻辑。我只是想简化它以在此处发布if(false && true || true) { /* do stuff */ }。我想我不明白优先级如何影响结果。我一直认为第一个失败的条件会使操作短路并且进一步的评估停止。
    • ...感谢您的进一步解释。这是一个新概念——不知道它是如何让我避开了 10 年的。我可以在几分钟内接受。
    • 我仍然不明白 false && (anything) 总是假的false && (anything) || somethingelse 可能是真的。无需进一步解释……去做研究。
    • @RyanWheale 哦,这是个好问题。等一下,无论如何,为了未来的读者,我将在我的答案中编辑另一段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    相关资源
    最近更新 更多