0

I have noticed when using the OR logic or the nullish coalescing together with the includes method in a ternary fashion.

 const result = 'Hello' || ['e', 'z'].includes('e') ? 'in-array' : 'not-in-array';
 console.log(result) // 'in-array'

 const result = 'Hello' ?? ['e', 'z'].includes('z') ? 'in-array' : 'not-in-array';
 console.log(result) // 'in-array'


 const result = 'Hello' || ['e', 'z'].includes('xx') ? 'in-array' : 'not-in-array';
 console.log(result) // 'in-array'

 const result = 'Hello' ?? ['e', 'z'].includes('xx') ? 'in-array' : 'not-in-array';
 console.log(result) // 'in-array'

To make it work, you will have to add parentheses/round brackets to the right end condition.

 const result = 'Hello' || (['e', 'z'].includes('e') ? 'in-array' : 'not-in-array');
 console.log(result) // 'Hello'

 const result = 'Hello' ?? (['e', 'z'].includes('z') ? 'in-array' : 'not-in-array');
 console.log(result) // 'Hello'

Is this an expected behaviour? Why is this happening?

4
  • 6
    You may want to familiarize yourself with operator precedence. The solution you've already discovered is how to address it. Commented Jun 3, 2024 at 21:02
  • 3
    This isn't weird behavior. There isn't any particular reason for your desired operator precedence to be the actual precedence. Commented Jun 3, 2024 at 21:04
  • 2
    @MarvineBamba: Why specifically do you think it should? What value do you expect the expression 'Hello' ?? ['e', 'z'].includes('xx') to evaluate to and why? Commented Jun 3, 2024 at 21:07
  • 2
    'Hello' ?? ['e', 'z'].includes('xx') is truthy because it evaluate to "Hello", so the positive side of the ternary is taken, which gives you "in-array". The .includes() call is never executed. Commented Jun 3, 2024 at 21:29

1 Answer 1

3

Let's look at the expression:

a || b && c

From the point of view of pure boolean logic, it's ambiguous. One of those two operators must be performed first, but which should it be?

Is it this?

(a || b) && c

Or is it this?

a || (b && c)

In order to solve that ambiguity the language designers have decided that && has a higher precedence than ||, and will therefore happen before operators of lower precedence.

Which means that:

a || (b && c)

is the correct interpretation according to the language specification.

However, you can override that by using parentheses and this:

(a || b) && c

Will now do the || operator first, and then use the result of that as the left hand side of the && operator.


Same for ternaries. The || and ?? have higher precedence that the ? ternary operator.

This means that this:

a || b ? c : d

Is also ambiguous. Should a || b be the left hand side of the ternary? Or should the entire ternary be on the right side of ||? As you've noted, the resulting logic is different.

What happens, is that it is interpreted as:

(a || b) ? c : d

because || has higher precedence than ? does.

And if you want a different order, then you can use parentheses to define that order:

a || (b ? c : d)

This is just like basic math. What is the answer to this mathematical expression?

1 + 5 × 2

Is this 12? Or is it 11? Without operator precedence, it's ambiguous. With operator precedence that we all agree on, the answer is 11 because × has higher precedence than +.

And again, you can always override that with parentheses:

(1 + 5) × 2 // 12
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.