带有多个条件的javascript if语句会测试所有条件吗?


100

在javascript中,当使用具有多个条件的if语句进行测试时,javascript是否会全部测试它们,如果已经为false,则在测试所有条件之前会保释吗?

例如:

 a = 1
 b = 2
 c = 1

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

javascript将测试所有这三个条件,还是在看到b不等于1并因此为false之后,将退出该语句?

我从性能的角度出发。例如,如果我正在测试3个复杂的jQuery选择器,那么我不希望jQuery遍历DOM 3次(如果通过第一个可以看出,它将返回FALSE)。(在这种情况下,嵌套3个if语句会更有意义)。

附录:出于好奇,这的恰当用语是什么?我注意到许多人使用“短路”一词。另外,某些语言会这样做吗,而其他语言不会吗?


@Josh:我完全赞赏这是微优化的想法。哪个好知道。就是说,如果一个选项比另一个选项更优化,我认为知道并养成使用所述方法的习惯是一件好事。(此外,我对答案也很好奇)
DA。

21
严格来说,这不是过早的优化。在具有短路逻辑的语言中,重要的是要知道在什么条件下某些方法将不被执行。例如,如果您依赖于它们的副作用。
罗布

5
这是关于“短路评估”的另一个问题:stackoverflow.com/questions/1232603/…–
David

@大卫。谢谢!有趣的阅​​读。
DA。

Answers:


151

&&运营商“短路” -也就是说,如果左边的条件是假的,它不打扰评估是正确的。

同样,||如果左侧条件为真,则操作员会短路。

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


1
极好的答案(技术部分和管理问题)。谢谢!
DA。

5
如果您确实希望它执行布尔语句的所有部分,则可以使用&和| |。分别为-和/或
Zoidberg

25
这种情况不一定总是与性能有关。有时,您可能正在做一个空检查,并说您的空检查是否为条件a,然后尝试对第二个检查进行(b ==值+ 1),如果同时检查了所有三个条件,则会出错。
infocyde

4
确实,短路与性能无关。但是,最初的问题是从性能角度出发。
Anon。

1
很好。进行此类微优化(以及其他操作)可能会对滚动事件循环产生重大影响,例如,对于多个元素的视差计算,甚至是粘性条。以这个例子为例:if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)第二个条件是一个更昂贵的计算,第一个条件只是一个布尔值。:)
安东尼

13

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

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

如果我们调用3个返回布尔变量的函数,则每个函数可能会花费很长时间,不仅重要的是要知道这种短路,而且要以什么顺序知道。例如:

if (takesSeconds() && takesMinutes())

if (takesMinutes() && takesSeconds())

如果两者同样有可能返回false。



10

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

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

应使用这些真的很用心,因为位运算符是对他们的操作数的单位工程和算术运算符不能总是充当“非短路”的版本&&||

例:

-2147483648 && 1 = 1 

-2147483648 & 1 = 0

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


1
这个答案是错误的。&和| 是按位运算符,它们不是'&&和||的非短路版本。按位运算符是对运算数的单个位进行运算的算术运算符。例如:-2147483648 && 1 = 1,但-2147483648&1 = 0更多资讯:en.wikipedia.org/wiki/Bitwise_operation
最大

1
@Max实际上我不知道这一点,自从我学习C以来就一直在使用它(我现在称之为“技巧”)。幸运的是,这种破坏我代码的输入从未出现过。我更正了我的答案,我欠您
ivcandela

@DJDaveMark对不起,我无法让您的false && (alert(""))解决方案正常工作:/
ivcandela,

@ivcandela我也不能。如果我不在手机上,那我将对其进行第一次测试; o)可惜,您无法编辑评论。我刚刚删除了它,并在下面添加了另一个
DJDaveMark

强制评估的更简单更好的方法是将结果保存在变量中,然后对变量进行测试,例如:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

如果第一个条件为真,它将仅测试所有条件,并亲自测试:

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


3

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

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

第二个评估依赖于第一个评估,如果第一个条件失败,则response.authResponse为null或未定义等时,第一个评估为true,并且不会引发编译错误。

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



2

对于任何对此问题感到困惑的人,是因为||?诸如此类的运算符结合使用时,他们没有看到短路行为:

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)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.