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

JavaScript conditional not short circuiting like I would expect

本文关键字:短路 期望 条件 JavaScript      更新时间:2023-09-26

我是一个经验丰富的开发人员,但我刚刚遇到了一个问题,花了我一段时间才弄清楚,正在寻找解释。我依靠短路,花了比我愿意承认调试的时间多。如果这属于另一个堆栈 交换站点,请告知。

我希望以下内容的评估结果为假,但它通过了:

(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

逻辑 AND ( && ) 的优先级高于逻辑 OR (|| )。

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

x && (y || z);

但是,改用显式 if 语句会更具可读性:

if (x && y) {
    z;
}

下面是 JS 中运算符优先级的参考图表。(参见#13和#14。

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

x * y + z;

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

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

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

短路不会调用退出整个操作的某种"中止"函数。只是布尔运算符将忽略他们的第二个参数(b a && b),如果它已经可以确定最终结果是什么。(例如,false && (anything)总是假的,所以&&很懒惰,不会费心计算第二个参数。

我仍然不明白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)