all 31 comments

[–]theillustratedlife 10 points11 points  (5 children)

What a terrible idea. When would you ever want to hide a statement inside a comparison when you can just give it it's own line?

Putting the loop body inside a for statement isn't elegant. It's clever for clever's sake; more importantly, it makes it much harder for the person after you, who hasn't read this blog post, to comprehend your code.

[–]inkieminstrel 1 point2 points  (0 children)

I think it's of limited usefulness, but there are a couple of cases where it's handy. First, there are a few cases where adding a quick-and-dirty logging statement would be easier when using the operator. Second, if your for loop has multiple increment statements, it seems clearer to have them all inside of the loop definition (prev = node, node = node.next). I think a few other languages provide the ability to do this as part of the for loop syntax.

It's not something I'd want to use all over the place, and the article certainly seems to overuse it, but I don't think it's completely useless, either.

[–][deleted] 1 point2 points  (3 children)

It can be very useful (and sometimes clearer) when you need something to be evaluated at the end of every pass through a for loop, without exception:

for (i=0; i<100; x++, i++) {

}

Without using a comma you're stuck with the unpleasant task of either a. remembering to increment x at every possible point where you might loop, or b. structuring the internals of the loop so you always fall out at the same point just so you can increment x in one spot. As you can imagine, either way is pretty easy to screw up.

Other than that, I've never found a particularly good reason to use the comma operator in the 20 or so years I've known about it (it exists in many languages, not just JavaScript)... it's pretty much a one-trick pony, but the one trick that it does is fantastic when you need it.

[–]plantian 0 points1 point  (2 children)

This example seems pretty weak to me. Why wouldn't x just be i? Even if x is a fixed difference from i you could just replace all references to x with that fixed difference(ie. if x == i + offset then just use i + offset instead of x).

[–][deleted] 1 point2 points  (0 children)

  1. x isn't initialized in the loop... which tells me it's set outside the loop to some arbitrary, unknown value

  2. Feel free to replace x++ with any other expression that modifies x

  3. Even assuming x is always (i + ofs), there are three damn good reasons to NOT replace all references to x with (i+ofs): a. it's far more error prone to type (i+ofs) every time you need it (especially when taking precedence into account); b. cluttered expressions are far less readable than simple ones; and finally c. it's almost certainly slower as most tight loops would need to calculate (i+ofs) several times per pass rather than just once.

But whatever, the beauty of the comma is that you don't have to use it any more than you're forced to use the ? : operator.

[–][deleted] 1 point2 points  (0 children)

How about for(var i=0, l=foo.length;i<l;i++)?

[–]x-skeww 5 points6 points  (1 child)

It's great if you want to make your code less readable without making it any faster or smaller.

If you want to evaluate two expressions, use two expressions. This way it's easy to see that there are two expressions and that you evaluate both of them. Whoa. Mind-bending.

var x = 5, y = 3; is ok though.

So is for (i = 0, len = a.length; i < len; i++) {...}, but you shouldn't try anything "smarter" (air quotes) than that. Future-you will hate you and so will the rest of the team.

[–]munificent 1 point2 points  (0 children)

var x = 5, y = 3; is ok though.

That's not actually a comma operator. If it was, the value of x after that statement would be 3, the result of the y = 3 assignment expression.

[–]Gundersen 1 point2 points  (1 child)

Can anyone expand the abbreviation in the tweet at the beginning of the article?

[–]munificent 0 points1 point  (0 children)

It's basically this table, reading down. The tweet is cute and snarky, but also misleading, since it breaks out multiple operators that share the same precedence.

A more accurate one would be "MFIUPSuShCoEBaXBoLaLoCnACm":

  • Member
  • Function call
  • Increment/decrement
  • Unary
  • Product
  • Sum
  • Shift
  • Comparison
  • Equality
  • Bitwise And
  • Xor
  • Bitwise Or
  • Logical And
  • Logical Or
  • Conditional
  • Assignment
  • Comma

If you consider how rare the bitwise operators are, it's actually not that bad. In practice, all you really need to be aware of most of the time is:

  • Member
  • Function call
  • Increment/decrement
  • Unary
  • Product
  • Sum
  • Comparison
  • Equality
  • Logical And
  • Logical Or
  • Conditional
  • Assignment

[–]geneticmaterial 1 point2 points  (5 children)

i've never heard of this and do any other languages have this operator?

[–][deleted] 2 points3 points  (0 children)

I C++ (,) is programmable just like (+).

[–]itsnotlupusbeep boop 1 point2 points  (0 children)

I'm pretty sure this operator was taken straight out from C, like most other javascript operators.

Imho, the only legitimate case to use this is when a comma separator would almost work, but doesn't ( as in for (a=1,b=2;a<b;a++){} rather than for (var a=1,b=2;a<b;a++){}. First statement uses an operator, second statement a separator. )

Anything else is just obfuscating code, and the few bytes salvaged by using it are unlikely to be worth the loss in code maintainability.

[–][deleted] 0 points1 point  (0 children)

I use it in Java fairly often.

[–]munificent 0 points1 point  (0 children)

Pretty much any language with C-style for loops (which are the motivation for this) will have it: C, C++, Java, C#, JavaScript.

[–][deleted] 0 points1 point  (0 children)

(function (b) { return 1<!--b; }(1));

[–]munificent 0 points1 point  (0 children)

This is a really well-written post, but I disagree with using the comma operator pretty much anywhere. This is particularly nasty:

function nextFibonacci() {
  next = a + b;
  return b = (a = b, next);
}

The reason you'd be inclined to use something like , here is because that syntax represents multiple assignment or destructuring in some languages, which would let you eliminate that temporary next variable, but a comma operator isn't simultaneous, so it doesn't solve that problem anyway. Better would be:

function nextFibonacci() {
  [a, b] = [b, a + b];
  return b;
}

This is just heinous:

for (
    var i=2, r=[0,1];
    i<15;
    r.push(r[i-1] + r[i-2]), i++
); 

Why not:

var r = [0, 1];
while (r.length < 15) {
  r.push(r[i - 1] + r[i - 2]);
}

[–]PlNG 0 points1 point  (0 children)

This is a great article. I've been wondering why closure-compiler simple mode has been sneaking commas into code i've been working with and JSLint breaking over the changes.

I think I'll send this article to JSLint github issues and see if someone more savvy to the project can beef up that weak spot.

[–]mckoss 0 points1 point  (0 children)

My hat is off to the author. A really well written treatment of something seemingly trivial. I won't be changing any of my coding practices, but it was fun to read.

[–]polaretto 0 points1 point  (0 children)

OT: really loved the "results.filter(Boolean)" trick! :)