When is the comma operator useful?
I read this question about the "comma operator" in expressions (,
) and the MDN docs about it, but I can't think of a scenario where it is useful.
So, when is the comma operator useful?
Solution 1:
The following is probably not very useful as you don't write it yourself, but a minifier can shrink code using the comma operator. For example:
if(x){foo();return bar()}else{return 1}
would become:
return x?(foo(),bar()):1
The ? :
operator can be used now, since the comma operator (to a certain extent) allows for two statements to be written as one statement.
This is useful in that it allows for some neat compression (39 -> 24 bytes here).
I'd like to stress the fact that the comma in var a, b
is not the comma operator because it doesn't exist within an expression. The comma has a special meaning in var
statements. a, b
in an expression would be referring to the two variables and evaluate to b
, which is not the case for var a, b
.
Solution 2:
The Comma Operator is frequently useful when writing functional code in Javascript.
Consider this code I wrote for a SPA a while back which had something like the following
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
This was a fairly complex, but real-world scenario. Bear with me while I explain what is happening, and in the process make the case for the Comma Operator.
This uses Underscore's chaining to
Take apart all of the options passed to this function using
pairs
which will turn{ a: 1, b: 2}
into[['a', 1], ['b', 2]]
This array of property pairs is filtered by which ones are deemed to be 'actions' in the system.
Then the second index in the array is replaced with a function that returns a promise representing that action (using
map
)Finally the call to
reduce
will merge each "property array" (['a', 1]
) back into a final object.
The end result is a transformed version of the options
argument, which contains only the appropriate keys and whose values are consumable by the calling function.
Looking at just
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
You can see the reduce function starts with an empty state object, state
, and for each pair representing a key and value, the function returns the same state
object after adding a property to the object corresponding to the key/value pair. Because of ECMAScript 2015's arrow function syntax, the function body is an expression, and as a result, the Comma Operator allows a concise and useful "iteratee" function.
Personally I have come across numerous cases while writing Javascript in a more functional style with ECMAScript 2015 + Arrow Functions. Having said that, before encountering arrow functions (such as at the time of the writing of the question), I'd never used the comma operator in any deliberate way.
Solution 3:
The comma operator allows you to put multiple expressions in a place where one expression is expected. The resulting value of multiple expressions separate by a comma will be the value of the last comma separated expression.
I don't personally use it very often because there aren't that many situations where more than one expression is expected and there isn't a less confusing way to write the code than using the comma operator. One interesting possibility is at the end of a for
loop when you want more than one variable to be incremented:
// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
// loop code here that operates on items[i]
// and sometimes uses j to access a different array
}
Here you see that i++, j++
can be put in a place where one expression is allowed. In this particular case, the multiple expressions are used for side affects so it does not matter that the compound expressions takes on the value of the last one, but there are other cases where that might actually matter.
Solution 4:
Another use for the comma operator is to hide results you don't care about in the repl or console, purely as a convenience.
For example, if you evaluate myVariable = aWholeLotOfText
in the repl or console, it will print all the data you just assigned. This might be pages and pages, and if you'd prefer not to see it, you can instead evaluate myVariable = aWholeLotOfText, 'done'
, and the repl/console will just print 'done'.
Oriel correctly points out† that customized toString()
or get()
functions might even make this useful.