for
loops with only an initialization blockwhile
loops with no incrementor/decrementor statement||
and &&
operatorsThis is not the comma operator, but the use of a comma separator in variable assignment statements:
(function() {
var a = 1, b = 2, c, d;
console.log(a, b, c, d); // => 1 2 undefined undefined
})();
1 2 undefined undefined
undefined
Multiple declaration and assignment using one expression:
(function() {
var a = b = 1, c;
console.log(a, b, c); // => 1 1 undefined
})();
1 1 undefined
undefined
var a = (1, 2); // Only final value is assigned
console.log(a); // => 2
var a = 1;
var b = (a++, 2); // All expressions are evaluated, final value is assigned
console.log(a, b); // => 2 2
b = (a++, 3);
console.log(a, b); // => 3 3
b = (a++, a + 1); // Increment a by 1, then assign a + 1 to b
console.log(a, b); // => 4 5
2 2 2 3 3 4 5
undefined
Embedding a debugging expression:
var a = 1, b = 2;
b = (console.log(a, b), a++, a + 1); // => 1 2
console.log(a, b); // => 2 3
1 2 2 3
undefined
Resetting an iterator:
var arr = [1, 2, 3, 4];
for (var i = 0, len = arr.length; i < len; i++) console.log(arr[i++, i]);
2 4
undefined
||
and &&
operators¶Like the comma operator, the ||
and &&
operators also return only the final value assigned. But ||
only evaluates the second expression if the first is falsey, while &&
only evaluates the second expression if the first is truthy:
var a = 1, b = 2;
/* `a += 1` is evaluated but its value is discarded;
`c` is assigned the value of `b + 1` */
var c = (a += 1, b + 1);
console.log(a, b, c); // => 2 2 3
var a = 1, b = 2;
/* `a` is evaluated as truthy and evaluation stops;
`c` is assigned the value of `a` */
var c = (a || b + 1);
console.log(a, b, c); // => 1 2 1
var a = 1, b = 2;
/* `a` is evaluated as falsey and evaluation continues;
`c` is assigned the value of `b + 1` */
var c = (a === 0 || b + 1);
console.log(a, b, c); // => 1 2 3
var a = 1, b = 2;
/* `a` is evaluated as truthy and evaluation continues;
`c` is assigned the value of `b + 1` */
var c = (a === 1 && b + 1);
console.log(a, b, c); // => 1 2 3
var a = 1, b = 2;
/* `a` is evaluated as falsey and evaluation stops;
`c` is assigned the value 'false' */
var c = (a === 0 && b + 1);
console.log(a, b, c); // => 1 2 false
2 2 3 1 2 1 1 2 3 1 2 3 1 2 false
undefined
while
and for
loops¶i--
alone can be used as a while
loop iterator expression, without needing a separate incrementor or decrementor statement, because as long as the incrementor value is not modified anywhere else in the loop, the expression will not produce an infinite loop but will terminate at (and including) zero:
var i = 4; while (i--) console.log(i);
3 2 1 0
undefined
Using the comma operator to chain expressions (which might otherwise be written as separate statements) on one line:
var arr = [];
for (var i = 3; i > 0; i--) console.log(i), arr.push(i);
console.log(arr);
arr = [];
var i = 3; while (i--) console.log(i), arr.push(i);
console.log(arr);
3 2 1 [ 3, 2, 1 ] 2 1 0 [ 2, 1, 0 ]
undefined
Parentheses are not needed in the preceding code, but they help make the syntax clearer:
var arr = [];
// parens enclosing expressions joined by comma operator
for (var i = 3; i > 0; i--) (console.log(i), arr.push(i));
console.log(arr);
arr = [];
// parens enclosing expressions joined by comma operator
var i = 3; while (i--) (console.log(i), arr.push(i));
console.log(arr);
3 2 1 [ 3, 2, 1 ] 2 1 0 [ 2, 1, 0 ]
undefined
Using the comma operator to increment more than one iterator value in the initialization block of a loop:
for (var i = 0, j = 1; i < 3; i++, j++) {
console.log(i, j);
}
0 1 1 2 2 3
undefined
Using the comma operator to express more than one condition in a loop:
var n = 5, x = 1;
while (n > x, n !== 3) console.log(n), n--;
5 4
4
Another example, with no loop body statements. This is a good way to embed debugging expressions.
var i = 4;
while (console.log(i), i--);
4 3 2 1 0
undefined
Using the comma operator to include more than one iteration statement in a loop:
var arr = [];
for (var i = 0; i < 10; arr.push(i), i++); // Notice, no block following loop
console.log(arr); // => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
undefined
Grouping parentheses are not required in the preceding code, but they help make the syntax clearer:
var arr = [];
for (var i = 0; i < 10; (arr.push(i), i++));
console.log(arr); // => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
undefined
function foo() {
if (1 === 1) return true;
}
console.log(foo()); // => true
true
undefined
console.log((1 === 1) ? 'equal' : 'unequal'); // => 'equal'
var foo = (1 === 1) ? 'equal' : 'unequal';
console.log(foo);// => 'equal'
function foo() {return (1 === 1) ? 'equal' : 'unequal'};
console.log(foo); // => 'equal'
equal equal equal
undefined
Using the comma operator (here we need parentheses to group the expressions):
var arr = [];
console.log((1 === 1) ? (arr.push('equal'), 'equal') : 'unequal');
console.log(arr);
equal [ 'equal' ]
undefined
Example of concision using the comma operator in a ternary expression (from The JavaScript Comma Operator):
// player loses
lives ? (lives--, go()) : (gameOver(), exit());
// `if...else`, clearly demarcated blocks
function evenOrOdd(int) {
if (int % 2 === 0) {
return 'Even';
} else {
return 'Odd';
}
}
// Single-line `if` statement, implicit `else`
function evenOrOdd(int) {
if (int % 2 === 0) return 'Even';
return 'Odd';
}
// Ternary conditional operator
function evenOrOdd(int) {
return (int % 2 === 0) ? 'Even' : 'Odd';
}
// Using falsiness of zero
function evenOrOdd(int) {
return (int % 2) ? 'Even' : 'Odd';
}
// ES6 arrow function
var evenOrOdd = int => (int % 2) ? 'Even' : 'Odd';
function foo() {
var foo = ('foo' === 'foo')
? 'I am foo, I am really really foo'
: 'I am not foo';
return (foo === 'I am foo, I am really really foo')
? 'Foo is me'
: 'No foo';
}
console.log(foo()); // => 'Foo is me'
Foo is me
undefined
These two return statements are equivalent:
function foo() {return (1 === 1) ? true : false;}
function bar() {return (1 === 1);}
console.log(foo(), bar()); // => true true
true true
undefined
Returning a second value if the first is undefined:
(function() {
function foo() {
var bar;
return bar || 'foo';
}
console.log(foo());
})();
foo
undefined
All expressions in the return statement are evaluated, but only the final expression is returned:
var arr = [];
function foo() {
var str = 'foo';
return (arr.push(str), str);
}
console.log(arr); // []
console.log(foo()); // 'foo' <- return value
console.log(arr); // ['foo'] <- result of evaluating `arr.push(str)`
[] foo [ 'foo' ]
undefined
function foo(n) {
return n + 1;
}
function bar(n) {
return n++, foo(n);
}
console.log(bar(1)); // => 3
3
undefined
Q: When you return only a variable assignment expression, you are producing a side effect and returning the evaluation of that expression?
var a = 0;
function foo() {return a = 1;}
console.log(foo());
console.log(a);
1 1
undefined
To return more than one value, return an array or object:
function foo() {return [1, 2]};
console.log(foo());
[ 1, 2 ]
undefined