Why does `false && true || true` evaluate to true?

10,516

Solution 1

Your confusion all comes down to a misunderstanding of precedence.

A mathematical analogue would be "Zero multiplied by anything equals zero." Consider the following expression:

0 x 100 + 5

In any programming language, or a decent calculator, this evaluates to 5. The "zero times anything" axiom is true - but the "anything" in this case is 100, NOT 100 + 5! To see why, compare it to this:

5 + 0 x 100

It doesn't matter whether you add the 5 at the beginning or the end - the operator precedence rules remove ambiguity from the statement.

In JavaScript boolean logic, && has higher precedence than ||. Since each operator is commutative, writing

false && true || true

is exactly the same as writing

true || false && true

Solution 2

You are looking at precedence wrong.

&& is done first, then || so what it looks like is how you wrote it:

(false && true) || true

So the MDN link is correct.

Solution 3

The language works by parsing an expression into abstract syntax tree. Your expression false && true || true gets parsed into this:

          ||
         /  \
       &&    true
      /  \
 false    true

Only after building the AST, the short-circuited evaluation can take place. The

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

quote applies only to a valid sub-tree where false and anything are subtrees of && node, like this:

       &&
      /  \
 false    true

which means only the false && true gets short-ciruit evaluated to false and resulting false || true is evaluated to true

Solution 4

Let's put it this way. Somebody who wrote this MDN article phrased it quite badly/did small mistake

As you pointed out it says:

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

And any reasonable person would assume that anything is logical expression of any complexity. However, this would be wrong reading (contradicting to boolean logic rules).

false && true || true == true

Two other answerers explained already why it's so. It's just an order of logical operators && and ||. First && is handled, next || is handled

Now, getting back to bad phrasing. What they should have said is following. Please notice additional parenthesis which I added.

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

I am using here parenthesis as a way to show that the rest of logical expression should have been evaluated independently of "false" part. If it's evaluated independently then short-circuiting it works fine because false && == false.

However, as soon as we have some expression which can't be evaluated independently then original phrasing doesn't work.

As example false && true || true can't be evaluated independently, because of order or logical operations. However false && doSomething() can.

Solution 5

JavaScript will parse this expression this way:

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

It's easy to trace how JavaScript parse this whole expression this way:

(function(){alert(1); return false; })() && 
(function(){alert(2); return true; })() || 
(function(){alert(3); return true; })()
Share:
10,516
Kyle Falconer
Author by

Kyle Falconer

I am a Software Engineer for Hopper with a Bachelor of Science in Computer Science from Missouri State University. Any opinions expressed by me are my own and not representative of Amazon's. I also do photography.

Updated on June 05, 2022

Comments

  • Kyle Falconer
    Kyle Falconer almost 2 years

    According to MDN Logical Operators page:

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

    Given this information, I would expect false && true || true to evaluate to false. However, this is not the case. The expected result (false) is only given when the statement is written like:

    false && (true || true)
    

    A coworker and I have tried to work this out and the closest thing we could come up with is that the statement is being evaluated by order of precedence. According to the MDN Operator Precedence logical-and has a higher precidence over logical-or, suggesting that the condition is evaluated as if false && true were a single statement, which then moves on to determine the boolean condition of false || true which is then true. Written out, this would be:

    (false && true) || true
    

    Something is wrong here. It's either the documentation, the JavaScript parsing logic, or my interpretation.

    Edit:

    I've added a bounty because none of the answers given truly understand the question. As stated above: the MDN Logical Operators page states exactly: "false && anything is short-circuit evaluated to false."

    "anything" means "anything"!