Javascript - Ternary Operator with Multiple Statements

Javascript

Javascript Problem Overview


Is this valid JavaScript? I saw an example where someone used commas in the ternary operator conditions, and it was marked as an error in my editor, and the example didn't run in Chrome. However, it did run in Firefox. Once I converted all the ternary statements to if/else statements, the app ran on Chrome.

a!==b ? (a=1, b=2) : (a=2, b=1)

Edit:

This is the actual statement in the code:

a!==0?b<0?(h=b/a,e=h-1,f=-2*b+2*a*e,i=-2*b+2*a*h,d=2*h*a-2*b-2*a):(h=b/a,e=h+1,f=2*b-2*a*e,i=2*b-2*a*h,d=-2*h*a+2*b):d=h=e=f=i=0

Javascript Solutions


Solution 1 - Javascript

Yes, it's valid, and it runs fine in Chrome:

var a, b, c;

a = 6;
b = 7;
c = a !== b ? (a = 1, b = 2) : (a = 2, b = 1);
console.log("a = " + a);
console.log("b = " + b);
console.log("c = " + c);

I'm not saying it's a remotely good idea in code humans are meant to read. :-) I expect jamietre is correct in the comments when he/she says it looks like the result of minification.

The comma operator is a binary operator (an operator accepting two operands). It evaluates its left-hand operand (thus causing any side-effects it has, such as assignment), throws that result away, then evalutes its right-hand operand (thus causing its side-effects if any) and takes that result as its result value. If you have multiple comma operators in a row, the overall expression is evaluated in order, left-to-right, with the final result being the value resulting from the right-most operand evaluation.

And of course, you know the conditional operator (a ternary operator — one accepting three operands) is used to pick one of two sub-expressions to evaluate, on the basis of an initial expression.

So that line is very...expressive...what with a total of seven* different expressions inside it.

So in that example, the result of the overall expression is 2 if a !== b initially, or 1 if a === b initially, with the side-effects of setting a and b.

It's the side effects that make it, in my view, a questionable choice. And of course, there's no reason to use the comma operator if the left-hand operand doesn't have side effects.


* Yes, seven of 'em packed into that overall ternary:

  • a !== b
  • the first comma expression
  • a = 1
  • b = 2
  • the second comma expression
  • a = 2
  • b = 1

Re your edit with the actual statement, that one works too:

function test(a) {
    var b = 7,
        d = 1,
        e = 2,
        f = 3,
        g = 4,
        h = 5,
        i = 6;
    
    a!==0?b<0?(h=b/a,e=h-1,f=-2*b+2*a*e,i=-2*b+2*a*h,d=2*h*a-2*b-2*a):(h=b/a,e=h+1,f=2*b-2*a*e,i=2*b-2*a*h,d=-2*h*a+2*b):d=h=e=f=i=0;
    
    console.log("a = " + a);
    console.log("b = " + b);
    console.log("d = " + d);
    console.log("e = " + e);
    console.log("f = " + f);
    console.log("g = " + g);
    console.log("h = " + h);
    console.log("i = " + i);
}

test(0);
test(1);

.as-console-wrapper {
  max-height: 100% !important;
}

But wow, I hope this is minified, because if a person wrote that, they must really have a thing against anyone who's supposed to maintain it later... ;-)

Solution 2 - Javascript

Yes:

a=1;
b=2;

a!==b ? (a=1, b=2) : (a=2, b=1)

console.log(a);     // 1
console.log(b);     // 2

and:

a=1;
b=2;

a===b ? (a=1, b=2) : (a=2, b=1)

console.log(a);     // 2
console.log(b);     // 1

As you can analyze, changing the equality operator reacts correctly to our test if you look at the results.

Solution 3 - Javascript

Or you can do this :

b = a!==b ? (a=1,2) : (a=2,1);

Read here about comma operator.

> The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.

Solution 4 - Javascript

Expanding on this topic with ES6 code example. If you're using one side of the TRUE : FALSE argument to iterate thru all cases in one IF, it makes sense to separate the code as if it's a switch | case statement.

Nesting implies that there is branching logic, while it is logically nested, writing nested IF's complicates what we're doing in my example. Like a lawyer over explaining a problem to a jury. IMO, you want to explain the point in it's simplest form. For instance, I find this example the most logical way of expressing nested ifs where the TRUE is executed. The final false is your last else {} choreDoor is either 0,1 or 2:

choreDoor === 0 ? 
   (openDoor1 = botDoorPath,
	openDoor2 = beachDoorPath,
	openDoor3 = spaceDoorPath)
: choreDoor === 1 ? 
   (openDoor2 = botDoorPath,
	openDoor1 = beachDoorPath, 
	openDoor3 = spaceDoorPath) 
: choreDoor === 2 ?
   (openDoor3 = botDoorPath,
    openDoor1 = beachDoorPath, 
    openDoor2 = spaceDoorPath)
: false;

Solution 5 - Javascript

If you don't want to use the Comma operator (,) then you can use nested Conditional (ternary) operators instead.

var a = 6;
var b = 7;
var c = (a !== b)?  // true
        ((a = 1 || 1===1)? (b = 2) : null) // will first run a=1, then b=2
      : ((a = 0 || 1===1)? (b = 0) : null);

console.log("a = " + a);
console.log("b = " + b);
console.log("c = " + c);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteveView Question on Stackoverflow
Solution 1 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 2 - JavascriptSarfrazView Answer on Stackoverflow
Solution 3 - JavascriptTK OmbleView Answer on Stackoverflow
Solution 4 - JavascriptGregg BurnsView Answer on Stackoverflow
Solution 5 - JavascriptstomyView Answer on Stackoverflow