当运算符优先级表明不应该进行短路评估时,为什么这样做?

时间:2017-09-30 19:02:45

标签: javascript java operator-precedence short-circuiting

JavaScriptJava中,等于运算符(=====)的优先级高于OR运算符(||)。然而,两种语言(JSJava)支持if语句中的短路:

当我们if(true || anything())时,anything()未被评估。

您还可以使用以下表达式:true || foo == getValue()) - 例如在console.log(...);等输出语句中,或在作业中。

现在,根据运算符优先级,不应发生短路,因为=== = ==> ||就优先顺序而言。 (换句话说,首先应该进行比较,因为等同性检查具有比OR比较更高的优先级,因此应该调用getValue()。)但它确实如此。未调用getValue()(可以通过将输出语句放入其正文中来轻松检查)。

为什么(当操作员优先说它不应该时,短路是否工作)?
 或者我是否感到困惑?

3 个答案:

答案 0 :(得分:15)

  

或者我是否感到困惑?

你是。我认为将优先级视为分组而非排序要简单得多。它会影响评估的顺序,但只会影响,因为会改变分组。

我肯定不了解Javascript,但是在Java操作数中总是按照从左到右的顺序进行评估。 ==优先于||的事实仅仅意味着

true || foo == getValue()

评估为

true || (foo == getValue())

而不是

(true || foo) == getValue()

如果您只是考虑这种方式的优先级,然后考虑评估总是从左到右(例如,||的左操作数总是在右操作数之前进行评估),那么一切都是&# 39;简单 - 由于短路,getValue()永远不会被评估。

要从等式中消除短路,请考虑以下示例:

A + B * C

...其中ABC可能只是变量,或者它们可能是其他表达式,例如方法调用。在Java中,保证将其评估为:

  • 评估A(以后再记住)
  • 评估B
  • 评估C
  • 将评估BC
  • 的结果相乘
  • 使用乘法结果
  • 添加评估A的结果

请注意,即使*的优先级高于+A仍会在BC之前进行评估。如果您希望在排序方面考虑优先级,请注意在添加之前乘法仍然如何发生 - 但它仍然满足从左到右的评估顺序。

答案 1 :(得分:0)

根据语言规范,https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24

  

在运行时,首先计算左侧操作数表达式;如果结果具有布尔类型,则进行拆箱转换(§5.1.8)。

     

如果结果值为true,则条件或表达式的值为true,并且不评估右侧操作数表达式。

因此,如果您有a || b==c,则不会将其解释为(a || b) == c,因为||的优先级较低,正如您在教程中找到的那样。相反,它被解释为a || (b==c)。现在a||的左侧,因此首先对其进行评估。

答案 2 :(得分:0)

在这种情况下没有运算符优先级。你在质疑的问题就像在f(callback)语句中callback函数甚至在f之前被评估一样。这不可能发生。

另一方面,在JS中,||是少数几个可以在节目中观看懒惰的地方之一。 ==操作数(好像它是一个类似于全功能语言的中缀函数)需要两个参数,左边的一个首先得到评估。如果它解析为true,则第二个参数甚至不会被评估。