Reputation: 806
Caught a bug in my code, where I'm using foo = bar || baz
to assign to baz if bar is undefined, however when using a ternary expression for the second argument, JS would assign the true value for the ternary expression, regardless of the first value.
Opened up the console and tested it. Seems that JS doesn't even evaluate the conditional expression, as seen here, where b isn't defined, but it still returns the true value for it.
>>> a = 1 || 2
1
>>> a = 0 || 2
2
>>> a = 1 || b
1
>>> a = 1 || b ? 3 : 4
3
>>> b
ReferenceError: b is not defined[Learn More]
>>> a = 1 || ( b ? 3 : 4 )
1
I am able to get the correct result by wrapping the ternary expression in ()s, but what's going on here? Why does it return 3 in the above test-case?
Upvotes: 0
Views: 29
Reputation: 370659
||
is lazy - it will not attempt to evaluate the right-hand side of a ||
of the left-hand side is determined to be truthy. If you had done b || 1
instead of 1 || b
, it would have tried to evaluate b
first, and an error would be thrown:
const a = b || 1 ? 3 : 4
The whole left side of the ?
is interpreted to be the condition. (Other operations performed on the left of a ?
will also be parsed before the whole ?
condition is evaluated.) The conditional operator has one of the lowest operator precedences.
For
1 || b ? 3 : 4
the operator with the highest precedence there is ||
, at 5. So the two expressions across from the ||
get evaluated for "or" first:
1 || b
Since 1 is truthy, the whole 1 || b
evaluates to 1
without considering b
.
1 ? 3 : 4
Then the conditional operator is evaluated (precedence 4):
true ? 3 : 4
evaluates to
3
because the condition is true.
When you put parentheses around the conditional:
1 || ( b ? 3 : 4 )
Parentheses have the highest operator precedence, at 20 - the interpreter knows that everything inside the parentheses will evaluate to a single expression, without regard to what's outside the parentheses. So
1 || <something>
evaluates to
1
because 1 is truthy.
Upvotes: 1