为什么`假&&真||真的`评价为真吗?

时间:2014-01-25 02:14:30

标签: javascript logic short-circuiting

根据MDN Logical Operators页面:

  

false&&任何短路评估都是错误的。

鉴于此信息,我希望false && true || true评估为false。然而,这种情况并非如此。只有当语句写成:

时,才会给出预期结果(false
false && (true || true)

一位同事和我试图解决这个问题,我们可以提出的最接近的事情就是按照优先顺序评估该声明。根据{{​​3}} logical-and具有比logical-or更高的预测,建议将条件评估为false && true是单个语句,然后继续确定布尔值false || true的条件,即true。写出来,这将是:

(false && true) || true

这里出了点问题。它可以是文档,JavaScript解析逻辑,也可以是我的解释。

编辑:

我添加了赏金,因为所给出的答案都没有真正理解这个问题。如上所述:MDN Operator Precedence页面确切地说明了:“false&&&&&& of short-circuit is short circuit to false。”

“任何事物”都意味着“任何事情”!

12 个答案:

答案 0 :(得分:9)

你正在看优先级错误。

&安培;&安培;首先完成,然后是||所以你看起来是怎么写的:

(false && true) || true

所以MDN链接是正确的。

答案 1 :(得分:9)

该语言通过将表达式解析为抽象语法树来工作。你的表达式false && true || true被解析为:

          ||
         /  \
       &&    true
      /  \
 false    true

在构建AST之后只有,可以进行短路评估。

  

false&&任何短路评估都是错误的。

quote仅适用于falseanything&&节点的子树的有效子树,如下所示:

       &&
      /  \
 false    true

这意味着只有false && true评估短期评估为false,结果false || true评估为true

答案 2 :(得分:9)

你的困惑归结为对优先权的误解。

数学模拟将是“零乘以任何等于零”。请考虑以下表达式:

0 x 100 + 5

在任何编程语言或一个体面的计算器中,这个评估为5.“零时任何事情”公理是正确的 - 但在这种情况下,“任何事情”都是100,而不是100 + 5!要了解原因,请将其与此进行比较:

5 + 0 x 100

无论是在开头还是结尾添加5都没关系 - 运算符优先规则从语句中删除歧义。

在JavaScript布尔逻辑中,&&的优先级高于||。因为每个运算符都是commutative,所以写

false && true || true

与写作完全相同

true || false && true

答案 3 :(得分:4)

JavaScript会以这种方式解析这个表达式:

1) false && true //evaluates to false
2) false || true //equals true. The first false is the result above

很容易跟踪JavaScript如何以这种方式解析整个表达式:

(function(){alert(1); return false; })() && 
(function(){alert(2); return true; })() || 
(function(){alert(3); return true; })()

答案 4 :(得分:4)

我们这样说吧。写这篇MDN文章的人说得非常糟糕/做了小错误

正如你所指出的那样:

  

false&&任何短路评估都是错误的。

任何理智的人都会认为任何是任何复杂性的逻辑表达。但是,这将是错误的阅读(与布尔逻辑规则相矛盾)。

false && true || true == true

另外两位回答者已经解释了为什么会这样。这只是逻辑运算符&& amp;和||。第一&&处理,下一步||处理

现在,回到糟糕的措辞。他们应该说的是以下内容。请注意我添加的附加括号。

false && (anything) is short-circuit evaluated to false.

我在这里使用括号作为一种方式来表明逻辑表达式的其余部分应该独立于“假”部分进行评估。如果它是独立评估然后短路它工作正常,因为假和&& == false。

然而,只要我们有一些无法独立评估的表达式,那么原始措辞就不起作用。

由于顺序或逻辑操作,无法独立评估示例false && true || true。但是false && doSomething()可以。

答案 5 :(得分:2)

首先考虑这个基本的算术表达式:

A * B + C

乘法优先,因此结果为

(A * B) + C

同样,&&优先,所以

A && B || C

与:

相同
(A && B) || C

就短路而言,如果AnythingB,那么可能缩写的Afalse。所以,如果你有类似的东西:

(false && takesALongTimeToDetermine()) || true

它会跳过评估takesALongTimeToDetermine()

我应该注意到这一点:短路永远不会改变答案。这是一个优化。由于&&只能评估为true,如果两个操作数均为true,如果第一个操作数为false,它将不会检查第二个操作数是什么,因为它已经知道答案是false。使用||进行倒数优化:如果第一个操作数为true,则它将返回true而不考虑第二个操作数的值。 此优化存在,以便您的代码运行得更快 - 它永远不会改变答案。在MDN中提到它的唯一原因是因为如果你的&&和有一个操作数需要比另一个更长的计算时间,你需要将其列为第二个。 (这也很重要,因为如果takesALongTimeToDetermine()做了除了返回一个值之外的其他东西,IE,如果它打印出你期望的日志语句,如果函数被短路,你将看不到它。但是这仍然是与&&返回的答案无关。)

答案 6 :(得分:1)

你说MDN Logical Operators上的措辞有点含糊不清。

您不应该将任何视为 && 之后的任何内容,而应将任何右侧操作符视为{{1} }

&&需要2个表达式:一个位于&&的左侧,另一个位于右侧。

在您的示例中:&&,false是左表达式,第一个true是右表达式。以下false && true || true不是|| true运算符将评估的内容的一部分。

短路意味着不会浪费评估正确表达式的周期,如果它不再影响逻辑运算符的结果。

在此示例中,这意味着&&的右侧表达式(true)将被忽略(因为false && true不是该表达式的一部分)

所以在执行中,这将会发生:

  • 首先评估逻辑运算符|| true
  • &&的两侧有2个表达式,需要进行评估
  • 第一个表达式(&&)计算结果为
  • 第二个表达式(false)被短路,因为无论结果如何,逻辑运算符都不会产生除true
  • 之外的任何结果
  • false已经评估为false && true
  • 下一步将评估逻辑运算符false||的结果为false && true,因此false}
  • 第一个表达式(false || true)计算结果为
  • 第二个表达式(false)计算结果为真
  • true已被评估为true。
  • 最终结果:false || true

答案 7 :(得分:0)

您可能缺少的是,运营商只考虑运营商每一方的单一参数。

所以来自:false && true || truetrue比较时,仅考虑第一个false

因此,此评估结果为false || true,最终评估为true

MDN article中的“任何”部分,在您的情况下可能会有点误导。

答案 8 :(得分:0)

这个求值为true的原因是因为OR的优先级高于AND,所以它的等价语句是:

(false && true) || true

这是一个重言式,因为false || true将始终评估为真。

答案 9 :(得分:0)

  

False boolean = 0;

     

True boolean = 1;

     

“&安培;&安培;” operator =乘法运算;

     

“||” =另外;

好吗?所以,如果你有这个:

if(true && false || true)

等于:

((1 x 0) + 1)

答案 10 :(得分:0)

您的解释是错误的,并且您的运算符优先级是为什么它的计算结果为true是正确的。您遗漏的是anything在抽象语法树的上下文中的含义。

由于操作的顺序,你最终会得到像

这样的树
          ||
      /        \
     &&        true
   /    \
false   anything

anything的范围,不包括树右侧的真实。

您可以看到some notes from Ohio State on ASTs here。它们适用于所有语言。

答案 11 :(得分:-2)

“false&& any”中的“false”和“nothing”绝对是指Javascript表达式/值(如@ Erbureth的答案中所示),而不是源代码。以下是证明这一陈述的例子:

“短路”的Javascript代码(每行一个)

var a=false; a && 3
!1 && alert("Never!")
(1==2) && "x"

没有“短路”的Javascript代码(每行一个)

<script>false && </script><p>Other page content...</p></body></html>
false && * x^.++@; true
"false && true"

希望这些无聊的示例有助于阐明为什么应用您引用源代码的规则毫无意义。该规则意味着应用于解析源代码后得到的值/子树(此时已应用操作顺序)