We continue the
topic of operators, this time you will find a story about the operator comma.
Let's start with a funny tweet:

')
The 'c' at the end is a comma operator. Last in the list of significant operators, little documented, but very useful. It is not so common, but I really like it. She is simple, elegant, and it is better to be on good terms with her.
What she does?
The comma operator performs both operands (from left to right) and returns the value of the second operator. (
MDC )
var a = (7, 5); a; //5 var x, y, z x = (y=1, z=4); x; //4 y; //1 z; //4
Why in your example are variable assignments surrounded by parentheses?
Due to the priority of the operators. A JavaScript expression may contain several different operators. The following expression contains three operators (* + and,):
return 5 * 2 + 3, 22;
The precedence of the operators determines in which order the operands within the expression will be executed.
Full list of operators
here . Operator comma has the lowest priority of all operators. Let's look at an example:
//original return 5 * 2 + 3, 22; //apply * operator return 10 + 3, 22; //apply + operator return 13, 22; //apply , operator return 22;
Now let's see what happens if we remove the parentheses:
By framing the expression with parentheses, we create a group that has the highest priority.
This ensures that the comma operator is applied first.
In practice, thanks to its low priority, the comma is a powerful tool. In fact, she says to the interpreter: first look at what all the other operators around me are doing, and then let me decorate the result.
Some expressions contain several commas. How it works?
Each operator in the chain is processed sequentially from left to right.
var a = (1, 2, 3, 4); a;
This is equivalent to:
var a = (((1, 2), 3), 4)
What about commas used in type literals and in declarations?
These delimiters are not really comma operators. The purpose of the delimiter-comma is the division of the members in the list. For example:
Why use the comma operator?
Because it allows you to execute several expressions in the place where JavaScript expects only one. Operators with a comma are not so common, rarely important, but very elegant:
var r = [], n = 0, a = 0, b = 1, next; function nextFibonacci() { next = a + b; return b = (a = b, next); // <<< } while(n++ < 10) { r.push(nextFibonacci()); } r; //[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
function getRandomPrime() { while(n = Math.round(Math.random()*1000000000), !isPrime(n)); // <<< return n; } var isPrime = function(n) { d = Math.ceil(Math.sqrt(n)); while(n%(d
Is a semicolon a disguised comma?
The semicolon is the declaration separator, and the comma is the expression separator inside the ads.
Why not use the && operator to execute multiple expressions sequentially?
The comma operator is very close to the && and || operator. All of these statements return the last expression they executed. That is the difference:
LHE - left expression
RHE - right expression
LHE && RHE1. Always performs LHE
2. if LHE is true, executes RHE
LHE || Rhe1. Always performs LHE
2. If LHE is false, executes RHE
LHE, RHE1. Always performs LHE
2. Always performs RHE
You should choose a comma if both expressions are to be executed.
What about examples?
As I noted earlier, the comma operator allows you to execute several expressions in the place where JavaScript expects only one.
For loops
Here is an alternative version of the Fibonacci number generator, which also uses the comma operator:
for ( var i=2, r=[0,1]; i<15; r.push(r[i-1] + r[i-2]), i++ ); r
For another example, consider a utility that helps the seller to choose the bills and coins that make up the buyer's delivery:
function toCurrency(total, values) { total *= 100; for( var i=0,counts=[]; counts[i]=total/values[i], total=total%values[i]; // i++ ); return counts.map(Math.floor); } toCurrency(32.47, [500, 100, 25, 10, 5, 1]); //[6, 2, 1, 2, 0, 2]
Same utility, but with formatting:
function toCurrency(total, values, sym) { total *= 100; //do the calc for( var i=0,counts=[]; counts[i]=total/values[i], total=total%values[i]; // i++ ); //format var results = counts.map(function(s,i) { return s>=1 && [Math.floor(s),"x",(sym || '$') + (values[i]/100).toFixed(2)].join(' '); }); return results.filter(Boolean).join(', '); } toCurrency(19.77, [500,100,25,10,5,1]); //"3 x $5.00, 4 x $1.00, 3 x $0.25, 2 x $0.01" toCurrency(19.77, [500,100,50,20,10,5,1], '£'); //"3 x £5.00, 4 x £1.00, 1 x £0.50, 1 x £0.20, 1 x £0.05, 2 x £0.01" toCurrency(19.77, [500,100,50,20,10,5,2,1], '€'); //"3 x €5.00, 4 x €1.00, 1 x €0.50, 1 x €0.20, 1 x €0.05, 1 x €0.02"
The following function uses a comma to simultaneously increase and decrease two variables inside the loop. At the output we get the curve:
function renderCurve() { for(var a = 1, b = 10; a*b; a++, b--) // console.log(new Array(a*b).join('*')); } renderCurve(); /* ********* ***************** *********************** *************************** ***************************** ***************************** *************************** *********************** ***************** ********* */
While loops
You can use the comma operator to create short versions of do-while loops.
This function searches for an ancestor from the list of elements named tagName (similar to jQuery parent).
function firstAncestor(el, tagName) { while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase())); return el; } //element in http://ecma262-5.com/ELS5_HTML.htm var a = $('Section_15.1.1.2'); firstAncestor(a, 'div'); //<div class="page">
Ternary operator
The ternary operator allows only one expression to be executed. If you need to execute several expressions, then you have to switch to if else. The comma operator is more readable in cases where it is used to combine short expressions:
//player loses lives ? (gameOver(), exit()) : (lives
Debag
The comma operator allows you to insert console.log anywhere without changing the code:
// products i > n var i=10, n=0, total=0; while(console.log(i,n), i
// var arr = [1,2,3]; for ( var i=0, total=0; i<arr.length; console.log(i,total), total += arr[i++]); )
// 4 var testArray = [3, 5, 8, 4], total = 0; var plusFour = testArray.map(function(e) {e + 4}) plusFour.forEach(function(n) {console.log(n), isNaN(n) || (total += n)});
Iterator binding
@wavded published one way to use a comma.
var colorIndex = 0, colors = ["FF0000", "008000", "FF0086", "A2FF00", "0000FF", "800080"]; function selectNextColor(){ return colors[colorIndex++] || colors[colorIndex = 0, colorIndex++]; }
Indirect eval call
eval
1 uses the context in which it was called. Therefore, there is no guarantee that calling eval in a loop will give the same result.
kangax wrote that we can use the comma operator to call eval indirectly, which will always be called in global context
2 :
var a = {}; (function() { eval("this.alert('If you can read this I must be global!')"); }).call(a);
1. Please, without holivars, everyone knows that eval is evil
2. The
ES5 standard says that any non-direct call to eval uses global context,
however, not all browsers support this rule (IE <= 8)
Conclusion
You can write excellent code without using the comma operator. Does this mean that I spent your time? I hope not. Extensive vocabulary makes writers and speakers more professional and access to the wide possibilities of the language can make us better coders. The more methods we know, the more beautiful, neat and readable code we can write. Good luck with the operator comma, share your examples of use!
Read
ECMA-262 5th Edition11.14 The comma operator10.4.2 Entering eval code15.1.2.1.1 Direct Call to EvalMozilla developer centercomma operatoroperator precedenceJuriy Zaytsev (
kangax ):
global eval, what are the optionsMark Harter (@wavded):
cycling through an array using the comma operatorUPD Took into account and corrected the shortcomings in the translation