Javascript - Ternary Operator with Multiple Statements

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... ;-)


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.


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.


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;

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);