JavaScript 条件不像我期望的那样短路

Posted

技术标签:

【中文标题】JavaScript 条件不像我期望的那样短路【英文标题】:JavaScript conditional not short circuiting like I would expect 【发布时间】: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

【问题讨论】:

【参考方案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 哦,这是个好问题。等一下,无论如何,为了未来的读者,我将在我的答案中编辑另一段。

以上是关于JavaScript 条件不像我期望的那样短路的主要内容,如果未能解决你的问题,请参考以下文章

Clickhouse:runningAccumulate() 不像我预期的那样工作

sleep() 不像我预期的那样工作

Android布局权重不像我想的那样工作

Foreach 循环不像我想象的那样[关闭]

异步函数的行为不像我对 Jest 的预期那样

使用 Linq 除了不像我想的那样工作