Can ternary operators contain multiple actions?

It is very-very important to note that : Can we use multiple actions in truthy/falsy part?

eg. if (condition)
{
action-1;
action-2;

}
else
{
action-n; //n th action
action-(n+1); // n+1 th action

}

in ternary form???

4 Likes

Yes, we can, but with one proviso… There is no block demarcation so that action should be simple, else it would be better to abstract it away in a function and call the function from the ternary.

Something we commonly see is console.log() as an action in each branch…

a % 2 === 0 ? console.log(`${a} is even.`) : console.log(`${a} is odd.`);

These are both simple actions that call the same function. Now let’s consider a couple things:

  • a ternary is an expression
  • console.log() accepts any expression and parses it as text characters to the console as best it can.

That means we don’t have to call the method in each branch, we can pass the entire ternary as the argument.

console.log(a % 2 === 0 ? `${a} is even.` : `${a} is odd.`);

All expressions boil down to one value. It’s that value that will be logged in this instance. The point here is that ternary expressions should be simple if they are to be easy to read and comprehend. They are not a de facto replacement for if..else, only a convenience to lighten the code.

Above I mentioned that ternaries have no block demarcation. Well, that’s not entirely true since JS recognizes ALL blocks, even if they have no keyword or identifier associated.

a % 2 === 0 ? {
    console.log(`${a} is even.`)
} : {
    console.log(`${a} is odd.`)
};

Now the reader can see the blocks and if they contain a few lines of code it will still be clear which branch of the ternary they are in. I rather doubt many teachers would go along with this, though.

Bottom line, keep your ternary expressions simple and well defined. The moment they get complicated, the reader could get muddled. That could make for some heady maintenance work that might otherwise go smoothly.

const doubleX = x => x * 2;
const halfX = x => x / 2;

const messingAround = a => a % 2 === 0 ? halfX(a) : doubleX(a);

See how the functions help abstract away the maths?

8 Likes

Addendum

We can return a function reference without invoking it, effectively giving the caller an object that can be called multiple times in the ensuing session.

const callbackChooser = a => a % 2 === 0 ? halfX : doubleX;

https://repl.it/@mtf/callbackChooser

1 Like

For those who are curious about else if statement in ternary operator

function example(…) {
    return condition1 ? value1
         : condition2 ? value2
         : condition3 ? value3
         : value4;
}

// Equivalent to:

function example(…) {
    if (condition1) { return value1; }
    else if (condition2) { return value2; }
    else if (condition3) { return value3; }
    else { return value4; }
}

Source MDN

8 Likes

You can chain/nest and have all kinds of fun with ternaries but whether you should is the bigger question and the answer is “it depends”.

Here’s the same code factored four different ways (comment out the other three and run it); the question is which is more desirable? Readable? Maintainable? (these are subjective):

function convertScoreToGradeWithPlusAndMinus(score) {
  if (score > 100 || score < 0) return `INVALID SCORE`;
  if (score < 60) return `F`;
  if (score > 97) return `A+`;

  let letter = `D`;
  if (score > 89) letter = `A`;
  if (score > 79) letter = `B`;
  if (score > 69) letter = `C`;

  let suffix = ``;
  let ones = score % 10;
  if (ones > 7) suffix = `+`;
  if (ones < 3) suffix = `-`;

  return letter + suffix;
}

function convertScoreToGradeWithPlusAndMinus(score) {
  if (score > 100 || score < 0) return `INVALID SCORE`;
  if (score < 60) return `F`;
  if (score > 97) return `A+`;
  let r = score % 10;
  return (score > 89 ? `A`
        : score > 79 ? `B`
        : score > 69 ? `C`
        : `D`).concat(
            r > 7 ? `+`
          : r < 3 ? `-`
          : ``);
}

const convertScoreToGradeWithPlusAndMinus = score => 
  (score > 100 || score < 0) ? `INVALID SCORE`
    : (score < 60) ? `F`
    : (score > 97) ? `A+`
    : (score > 89 ? `A`
      : score > 79 ? `B`
      : score > 69 ? `C`
      : `D`).concat(
          score % 10 > 7 ? `+`
        : score % 10 < 3 ? `-`
        : ``);

const convertScoreToGradeWithPlusAndMinus = score =>
  (score > 100 || score < 0) ? `INVALID SCORE` : (score < 60) ? `F` : (score > 97) ? `A+` : 
    (score > 89 ? `A` : score > 79 ? `B` : score > 69 ? `C` : `D`)
      .concat(score % 10 > 7 ? `+` : score % 10 < 3 ? `-` : ``);


for (let score = -1; score < 102; score++)
  console.log(score, convertScoreToGradeWithPlusAndMinus(score));