The Confusing Comma In JavaScript
Written by Ian Elliot   
Thursday, 24 October 2013

Not every comma in JavaScript is an operator - in fact most of them aren't. It is time to confront the confusing comma.

The comma operator in JavaScript is really very simple and, to be 100% honest, you never need to use it. What is more you probably shouldn't use it - but is this a reason for not understanding it?

No, of course not.

comma

The Basic Comma

The comma operator fits in with a set of expression operators that can be useful, but it has a tendency to be used in ways that confuse rather than clarify. Part of the reason for this is that it is a comma, and commas have other meanings in JavaScript. 

So to be 100% clear, the comma is only a comma operator when it acts on two expressions:

lefthand expression , righthand expression

Where expression is something that involves other operators, variables and functions. 

What does the comma operator do?

It evaluates each of the expressions, starting with the lefthand expression and returns the value of the righthand expression. 

For example

a = (1, 2);

stores 2 in a. Of course, the 1 and 2 are standing in for any complicated expression you care to think up, and you can use string expressions, functions and so on. 

But why the parentheses? 

The answer is that the comma operator has the lowest priority of all the JavaScript operators and without the parentheses the expression would be parsed as:

(a=1), 2;

which ends up storing 1 in a and throwing away the result of the righthand expression. 

If you use more than one comma then, by the rules of operator precedence and left associativity, the result is that each expression is evaluated in turn from left to right and the last one is returned as the result. That is:

(exp1, exp2, exp3, and so on expN)

evaluates exp1, exp2 etc. and returns expN as its result. 

Side Effects

For simple comma expressions like:

a = (1, 2);

the value of the lefthand expression is always lost - so why bother?

The answer is that some operators have side effects and most functions have side effects. 

For example, you can use:

a=(console.log(1),console.log(2),console.log(3),4);

and you will see 1,2,3 printed on the console and 4 stored in a.

Of course, given function calls and assignments are also statements we can use the semicolon:

console.log(1);console.log(2);console.log(3);a=4;

The point is that semicolons separate statements and commas separate expressions, and in some cases statements are also expressions. There are places where you can only use commas, but often you have a choice.

The problem here is that some programmers choose to use a comma just because it looks cool and this is just confusing. 

This Is Not The Comma You Are Looking For

One reason for confusion is that there are lots of places where commas are just separators. 

For example, in object literals:

var obj={a:0,b:1,c:function(){}};

the commas are just separators. 

In arrays:

var arr=[1,2,3,4];

the commas are just separators.

Perhaps most confusing of all is the var declaration. For example in:

var a=1,b=2,c=3;

the commas are just separators, not comma operators.  The reason is that the var statement is a declaration and an initialization equivalent to

var a;
var b;
var c;
a=1;
b=2;
c=3;

Things like a=1 is an expression; the value of the expression is, in this case one. This allows you to write things like:

a=b=1;

which is equivalent to a=(b=1) 

However:

var a=1; 

isn't an expression and doesn't have a value. Rather, it contains an expression because initialization is of the form:

var variable=expression;

or 

var var1=exp1,var2=exp2 and so on...

This is subtle, but if you are following you can see that just by adding a pair of parentheses we can turn the previous var example into something that does use the comma operator:

var a=(1,b=2,c=3);

What do you think is stored in a, b and c? 

The answer is that a is 3, b is 2 and c is 3. The statement is of the form:

var a=expression;

and the expression is:

(1,b=2,c=3)

which, by the rules of the comma operator, evaluates each sub-expression in turn, throws away each of the results except for the last, which is the value of the expression. Notice that the b=2 and c=3 are expressions, and if b and c don't exist they are created as global variables. 

Now you should be able to see why:

var a=1,(b=2,c=3);

is nonsense and just generates an error, but 

var a=1,b=(2,c=3);

is perfectly OK and declares two local varlables a and b.

What is stored in b?

Answer 3 because the expression is (2,c=3).

Using The Comma

So now we have the comma mastered - what can you use it for?

The honest answer is not much. 

There are places, espcially in libraries, where you will find the comma operator in use, but in most cases there are much better and clearer ways of expressing the same idea. 

The most commonly encountered use of the comma operator is to make more complex for loops. Really for loops should be kept simple so the idea of making them more complex isn't a good one.

A JavaScript for loop has the form:

for(expression1;expression2;experssion3)

Expression1 is evaluated once when the loop starts and it is usually where the initialization occurs. Expression 2 is evaluated before each new iteration of the loop. If it evaluates to false the loop stops. Expression 3 is evaluated at the end of each loop iteration and it is generally where loop counters etc are updated. Notice that you can write any expression you care to in a for loop and you can use the comma operator so that you can write multple expressions. 

So, for example, what do you think the following for loop is all about?

for(var i=0,j=10;i<=j;i++,j--){
 console.log(i*j);
}

The first expression isn't a use of the comma operator. It just uses the var statement to create two local variables, i and j, and sets them to zero and ten respectively. The second expression is a simple test for i being less than or equal to j, and doesn't use the comma operator. The final expression is the only use of the comma operator and it adds one to i and subtracts one from j each time through the loop. So the values of i and j we create are:

0 10
1 9
2 8
3 7
4 6
5 5

and then the loop ends.

Clever?

You could just as easily have written the loop as:

for(var i=0,j=10;i<=j;i++){
 console.log(i*j);
 j--;
}

You can use a similar technique to turn a while loop into a sort of for loop:

var i=0;
while(i++,i<10){
 console.log(i)
}

There are lots of similar uses and examples, but they all come down to the same thing - we need to use a single expression but also need to evaluate some other expressions first just for their side effects. 

Relationship To Active Logic

The comma operator can be thought of as being a member of the same family as &&, || and ?

If you need to brush up on these operators see Javascript Jems - Active Logic, Truthy and Falsey.

To summarize:

expressionA || expressionB

evaluates expressionA - if truthy then this is the result, otherwise the righthand expression is evaluated and is the result.

expressionA && expressionB

evaluates expressionA - if falsey then this is the result, otherwise the righthand expression is evaluated and is the result.

expressionA ? expressionB:expressionC

evaluates expressionA - if truthy it evaluates expressionB as the result and otherwise it evaluates expressionC as the result. 

The comma operator:

expressionA , expressionB

evaluates expressionA then the righthand expression is evaluated and is the result.

It is also worth noting that the comma operator works well with any of the other active logic operators. In particular, the the ternary operator ? can often make use of it. For example:

triesLeft ? (triesLeft--,try()):(noMoreTries(),Finish());

If you assume that triesLeft is a counter of how many attempts the user has then you can decrement it and call the try function or call a function that informs the user that they have failed and then stops the program. 

Conclusion

The situation is best summed up as "you need to understand the comma, but you probably don't need to use it".

What really matters is that you don't confuse the many other uses of the comma with the comma operator.

comma

Related Articles

Javascript Jems - Active Logic, Truthy and Falsey

True but not true       

Dangerous Logic - De Morgan & Programming       

JavaScript Bit Manipulation 

 

Banner


Just JavaScript - The Object Expression

As in most programming languages the expression is an important part of JavaScript, but it isn't quite the same. This is where the idea that JavaScript has some weird type conversions arises. But Java [ ... ]



Javascript Jems - Asynchronous Patterns And Closure

If you have ever been kept awake at night worrying about closure then this is for you? You can understand closure, but what is it for? We explain how it can be all so easy and really, really usef [ ... ]


Other Articles

  

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

 

blog comments powered by Disqus

 <ASIN:1430230541>

<ASIN:0321683919>

<ASIN:0596517742>

<ASIN:0321572602>

<ASIN:0596806752> 

Last Updated ( Thursday, 24 October 2013 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.