Short circuiting in place of ternary operator

Viewed 322

Try to learn short circuiting and doing some assignments . Have the following code

game.odds.team1 < game.odds.team2 && `${game.team1} is more likely to win` || `${game.team2} is more likely to win`

My understanding was that && operator treats left-side as 1 part of expression and whole right side as a 2nd part. So I don't quite understand why this returns {game.team2}.... in the end.

Could you help me clarify this please?

P.S. Just to be more precise, the code above works well and does what it has to do, but I struggle to understand how exactly it works and why it works this way.

4 Answers

The problem of this code is to have three parts which can change the result.

a < b && c || d
^^^^^    ^    ^

This answer takes the terms truthy and falsy especially for part c and d.

If the first condition a < b is true, it takes c as long as c is truthy. If not, it takes d.

If the first condition is false, it takes d, because of the short circuit &&.

For having a better understanding, here a table of truth. (- means value does not matter):

a < b c d result
true truthy - c
true falsy d d
false - d d

EDIT: the previous solution has been removed according to your question

As you only need to understand how short-circuit evaluation of logical operator works, so I will add the following explanation:

I - Keypoints:

1- logical AND operator && returns the first falsy value, and if all operands were evaluated, it returns the last one.

2- logical OR operator || returns the first truthy value, and if all operands were evaluated, it returns the last one.

3- The precedence of AND && operator is higher than OR ||

4- Check the table list of JS operators precedence

In your example, both operands (arguments) of the logical OR are truth (strings).

II - Example:

Starting from your code, let's consider this object of values:

const game = {
    odds: {
        team1: 10,
        team2: 3
    }
}

const winner = game.odds.team1 < game.odds.team2 && `$team1 is more likely to win` || `team2 is more likely to win`
console.log(winner)

Here, winner will be assigned to the last operand. But why? Let's break-down the logic (remember the keypoints):

1- game.odds.team1 < game.odds.team2 is false and $team1 is more likely to win is truthy as it's a string, then && will return the first falsy value.

2- game.odds.team1 < game.odds.team2 is returned (still false). and it's evaluated now with team2 is more likely to win which is a truthy string.

3- the logical OR return the first truthy value, therefore team2 is more likely to win is assigned to winner.

I hope it's clear now

My understanding was that && operator treats left-side as 1 part of expression and whole right side as a 2nd part

No, it doesn't. The && has a higher precedence than the ||. It's parsed as

((game.odds.team1 < game.odds.team2) && `${game.team1} is more likely to win`) || `${game.team2} is more likely to win`

But yeah, while it's a nice exercise you definitely should use the ?: conditional operator for this :-) Apart from expressiveness, another reason is that c ? t : e is not always equal to c && t || e. Can you figure out for which values of t that might be?

game.odds.team1 < game.odds.team2 ? `${game.team2} is more likely to win` : `${game.team1} is more likely to win`
Related