JavaScript Jems - The Comma
Written by Mike James   
Monday, 17 October 2022
Article Index
JavaScript Jems - The Comma
Using the Comma

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular it has the comma - what?This is an extract from JavaScript Jems: The Amazing Parts.

Jem 9

The Comma

I was working on the proof of one of my poems all the morning, and took out a comma. In the afternoon I put it back again.”
Oscar Wilde

Such a small thing to be a jem but JavaScript's comma operator deserves a second look. Not every comma in JavaScript is an operator - in fact most of them aren't.

Now available as a book from your local Amazon.

JavaScript Jems:
The Amazing Parts

kindlecover

Contents

<ASIN:1871962579>

<ASIN:1871962560>

<ASIN:1871962501>

<ASIN:1871962528>

The Basic Comma ,

The comma operator , fits in with a set of expression operators and it 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. To be 100% clear, the comma is only a comma operator when it acts on two expressions:

left-hand expression , right-hand expression

where expression is something that involves other operators, variables and functions, i.e. something that works out to a value.

What does the comma operator do? It evaluates each of the expressions, starting with the left-hand expression, and returns the value of the right-hand 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 right-hand 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 left-hand expression is always lost - so why bother? The answer is that some operators have side effects and most functions have side effects. Side effects are something that matters a lot in functional programming as we will discover in Jem 16, but meanwhile, put simply, a side effect is something that isn't just its result that is changed by a function when you run it. 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. The printing of values on the console is a side effect of calling the log function.

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;

This is because 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 this causes 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 and the same applies in arrays:

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

Again 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 this var statement is a declaration and is 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 1. 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 the 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 holds 3, b has 2 and c has 3. The statement is of the form:

var a=expression;

and 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, whereas:

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

is perfectly OK and declares two local variables, a and b. What is stored in b? The answer is 3 because the expression is (2,c=3).

kindlecover

 



Last Updated ( Tuesday, 18 October 2022 )