93

If I use:

1.09 * 1; // returns "1.09"

But if I use:

1,09 * 1; // returns "9"

I know that 1,09 isn't a number.

What does the comma do in the last piece of code?

More Examples

if (0,9) alert("ok"); // alert
if (9,0) alert("ok"); // don't alert

alert(1); alert(2); alert(3); // 3 alerts
alert(1), alert(2), alert(3); // 3 alerts too

alert("2",
    foo = function (param) {
        alert(param)
    },
    foo('1')
)
foo('3'); // alerts 1, 2 and 3
Topera
  • 11,264
  • 14
  • 59
  • 100
  • 1
    I'm surprised that 09 isn't failing for illegal '9' in octal literal. – recursive Aug 24 '10 at 21:11
  • 7
    @recursive - any 9 in octal representation results in a fallback to decimal. – Yuval Adam Aug 24 '10 at 21:14
  • Don't confuse the comma in an argument list. `alert` takes only one argument. Anything after that is discarded. – Andrew Aug 25 '10 at 01:42
  • @Andrew: yes, is discarded by alert(), that takes only one argument, but it will be runned! That's weird. Thanks. – Topera Aug 25 '10 at 01:43
  • 1
    @Topera: not really weird if you think about it from JS's perspective. In JS you don't have to specify your argument list in your function declaration (you can use the `arguments` object instead, which can be of any length). Even with modern compiled JS, there would be no way to tell ahead of time how many arguments a function would take. Consider this: `function test() { args=[]; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i] + 1); } ;` The interpreter would have to know how the function was being used to know how many args it would take. Instead, it evaluates everything. – Andrew Aug 25 '10 at 02:05

6 Answers6

100

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

Source: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special_Operators/Comma_Operator

For example, the expression 1,2,3,4,5 evaluates to 5. Obviously the comma operator is useful only for operations with side-effects.

console.log(1,2,3,4,5);
console.log((1,2,3,4,5));
Zze
  • 15,599
  • 9
  • 68
  • 98
Yuval Adam
  • 149,388
  • 85
  • 287
  • 384
  • 3
    They took it from C. I think it's only useful for expressions that have side effects. – Radomir Dopieralski Aug 24 '10 at 21:11
  • 3
    I can't think of many cases where the comma operator is used to any affect but saving characters (minifying) or obfuscating code. – user17753 Jan 30 '13 at 21:55
  • 2
    @user17753 it can be used legitimately in the semicolon-separated section of a `for` loop. – Cyoce Mar 24 '17 at 07:33
  • 1
    @Cyoce: While that's true, speaking generally such logic is more clearly performed in the loop body. Some people will then claim that their way allows for multiple `continue` points without duplication, but then you shouldn't have multiple `continue` points. – Lightness Races in Orbit Mar 21 '18 at 12:15
  • @user17753 You're on the money; trying to understand a small snippet of minified code is why I'm here – Seldom 'Where's Monica' Needy May 20 '20 at 22:25
  • `Vue` docs use it on their [template compilation example](https://v3.vuejs.org/guide/render-function.html#template-compilation) – Marinos An Apr 21 '21 at 11:14
6

Some more to consider:

console.log((0, 9));
console.log((9, 0));
console.log(("foo", "bar"));
Zze
  • 15,599
  • 9
  • 68
  • 98
Douglas
  • 32,530
  • 8
  • 68
  • 88
2
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

https://stackoverflow.com/a/3561056/5934465

It should be like this!

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

xgqfrms
  • 5,516
  • 1
  • 37
  • 42
  • 5
    The comma operator takes _two_ operands, so the original quote was correct. What you are talking about is the end result of nesting such expressions, but it means your replacement quote is subtly misworded. `a,b,c,d` is `((((a),b),c),d)` – Lightness Races in Orbit Mar 21 '18 at 12:16
0

Have a look here - the comma stands for multiple expressions / statements. For example in your code you could use a line like this:

var a=0, b=0, c=0;

This would declare all three variables without writing:

var a=0;
var b=0;
var c=0;

Hope that helps.

Drew Gaynor
  • 7,733
  • 5
  • 36
  • 50
dhh
  • 4,030
  • 8
  • 40
  • 56
  • 27
    It's a bit old, but important to note: (1) the example you have provided doesn't use the comma operator (`var` declarations don't use the comma *operator*, even though it's a comma) and (2) you can't separate statments using the comma operators; only expressions are allowed. – Qantas 94 Heavy Apr 26 '14 at 09:49
0

Adding/modifying properties to an object and returning it in the same line is a possible use-case:

console.log(
  ((x) => (o = {biggerCond: r => r >= x},
           o.r5 = Array.from(window.crypto.getRandomValues(new Uint16Array(5))),
           o.isAnyBigger = o.r5.some(o.biggerCond),
           o.bigger = o.isAnyBigger ? o.r5.filter(o.biggerCond) : [x], o )
  )(5e4)
);
// Example
// {
//   bigger: [58414, 56500, 63397],
//   isAnyBigger: true,
//   isBiggerCond: r => r >= x,
//   r5: [58414, 12015, 56500, 63397, 43861]
// }

The above anonymous function returns an object with random values bigger than the input value or, if there's none, with the input value itself in an array in contained in the bigger property.

It is still syntactic sugar (like arrow functions), but it does shorten the number of lines... I wonder if some JS minifiers detect and adjust the code in a similar way automatically. Run it in your console:

((x)=>(o={biggerCond:r=>r>=x},o.r5=Array.from(window.crypto.getRandomValues(new Uint16Array(5))),o.isAnyBigger=o.r5.some(o.biggerCond),o.bigger=o.isAnyBigger?o.r5.filter(o.biggerCond):[x],o))(5e4)
CPHPython
  • 6,842
  • 2
  • 41
  • 58
0

The specific syntax allows you to functionally bake bread and hand it to the customer to consume with no returns.

(new Array(3)).fill()
.map(()=>({state:"dough", bake(){this.state="baked"}, consume(){this.state="consumed"}}))

.map(bread=>(console.log(`Adding ${bread.state} to oven.`), bread.bake(), bread))
.map(bread=>(console.log(`Consuming ${bread.state} bread.`), bread.consume(), bread))
.map(bread=>console.log(`Bread is now ${bread.state}.`))
Adding dough to oven.
Adding dough to oven.
Adding dough to oven.
Consuming baked bread.
Consuming baked bread.
Consuming baked bread.
Bread is now consumed.
Bread is now consumed.
Bread is now consumed.
Marinos An
  • 6,191
  • 2
  • 35
  • 68