• JavaScript
  • JavaScript
  • Tutorials and guides
  • Beginner's tutorials
    1. JavaScript Guide
      1. Loops and iteration
      2. Representing dates & times
      3. Working with objects
      4. Iterators and generators
      5. Asynchronous JavaScript
      6. Equality comparisons and sameness
      7. Meta programming
      8. AggregateError
      9. AsyncGenerator
      10. BigInt
      11. DataView
      12. encodeURI()
      13. escape() Deprecated
      14. Float16Array
      15. Generator
      16. Int8Array
      17. InternalError Non-standard
      18. Iterator
      19. NaN
      20. parseInt()
      21. ReferenceError
      22. SharedArrayBuffer
      23. Temporal Experimental
      24. Uint8ClampedArray
      25. unescape() Deprecated
      26. WeakSet
  • Assignment (=)
  • Bitwise AND (&)
  • Bitwise OR assignment (|=)
  • Comma operator (,)
  • Destructuring
  • Exponentiation (**)
  • Greater than (>)
  • import.meta.resolve()
  • Inequality (!=)
  • Less than (<)
  • Logical NOT (!)
  • Multiplication assignment (*=)
  • Nullish coalescing assignment (??=)
  • Optional chaining (?.)
  • Right shift (>>)
  • Strict inequality (!==)
  • this
  • Unsigned right shift (>>>)
  • yield*
  • Block statement
  • continue
  • export
  • for...in
  • if...else
  • let
  • try...catch
  • with Deprecated
  • get
  • The arguments object
    1. callee Deprecated
    2. extends
    3. Static initialization blocks
  • Character class escape: \d, \D, \w, \W, \s, \S
  • Input boundary assertion: ^, $
  • Modifier: (?ims-ims:...)
  • Quantifier: *, +, ?, {n}, {n,}, {n,m}
  • Errors
    1. RangeError: argument is not a valid code point
    2. RangeError: invalid array length
    3. RangeError: repeat count must be less than infinity
    4. ReferenceError: assignment to undeclared variable "x"
    5. SyntaxError: 'arguments'/'eval' can't be defined or assigned to in strict mode code
    6. SyntaxError: \ at end of pattern
    7. SyntaxError: await is only valid in async functions, async generators and modules
    8. SyntaxError: continue must be inside loop
    9. SyntaxError: function statement requires a name
    10. SyntaxError: identifier starts immediately after numeric literal
    11. SyntaxError: invalid assignment left-hand side
    12. SyntaxError: invalid class set operation in regular expression
    13. SyntaxError: invalid property name in regular expression
    14. SyntaxError: invalid unicode escape in regular expression
    15. SyntaxError: missing ) after argument list
    16. SyntaxError: missing } after property list
    17. SyntaxError: missing variable name
    18. SyntaxError: numbers out of order in {} quantifier.
    19. SyntaxError: property name __proto__ appears more than once in object literal
    20. SyntaxError: rest parameter may not have a default
    21. SyntaxError: super() is only valid in derived class constructors
    22. SyntaxError: unlabeled break must be inside loop or switch
    23. TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed
    24. TypeError: "x" is not a function
    25. TypeError: BigInt value can't be serialized in JSON
    26. TypeError: can't convert BigInt to number
    27. TypeError: can't redefine non-configurable property "x"
    28. TypeError: class constructors must be invoked with 'new'
    29. TypeError: Initializing an object twice is an error with private fields/methods
    30. TypeError: Iterator/AsyncIterator constructor can't be used directly
    31. TypeError: property "x" is non-configurable and can't be deleted
    32. TypeError: X.prototype.y called on incompatible type
    33. JavaScript technologies overview
    34. Strict mode
    35. Learn more
    36. See full compatibility
  • The comma (,) operator evaluates each of its operands (from left to right) and returns the value of the last operand. This is commonly used to provide multiple updaters to a for loop's afterthought.

    Try it

    let x = 1;
    
    x = (x++, x);
    
    console.log(x);
    / Expected output: 2
    
    x = (2, 3);
    
    console.log(x);
    / Expected output: 3
    

    Syntax

    js
    expr1, expr2, expr3/* , … */
    

    Parameters

    expr1, expr2, expr3, …

    One or more expressions, the last of which is returned as the value of the compound expression.

    Description

    You can use the comma operator when you want to include multiple expressions in a location that requires a single expression. The most common usage of this operator is to supply multiple updaters in a for loop. For an idiom allowing multiple statements in a location that requires a single expression, you may use an IIFE.

    Because all expressions except the last are evaluated and then discarded, these expressions must have side effects to be useful. Common expressions that have side effects are assignments, function calls, and type coercions.

    The comma operator has the lowest precedence of all operators. If you want to incorporate a comma-joined expression into a bigger expression, you must parenthesize it.

    The comma operator is completely different from commas used as syntactic separators in other locations, which include:

    • Elements in array initializers ([1, 2, 3])
    • Properties in object initializers ({ a: 1, b: 2 })
    • Parameters in function declarations/expressions (function f(a, b) { … })
    • Arguments in function calls (f(1, 2))
    • var declarations (const a = 1, b = 2;)
    • Import lists in import declarations (import { a, b } from "c";)
    • Export lists in export declarations (export { a, b };)

    In fact, although some of these places accept almost all expressions, they don't accept comma-joined expressions because that would be ambiguous with the syntactic comma separators. In this case, you must parenthesize the comma-joined expression. For example, the following is a const declaration that declares two variables, where the comma is not the comma operator:

    js
    const a = 1, b = 2;
    

    It is different from the following, where b = 2 is an assignment expression, not a declaration. The value of a is 2, the return value of the assignment, while the value of 1 is discarded:

    js
    const a = (1, b = 2);
    

    Comma operators cannot appear as trailing commas.

    Examples

    Using the comma operator in a for loop

    If a is a 2-dimensional array with 10 elements on each side, the following code uses the comma operator to increment i and decrement j at once, thus printing the values of the diagonal elements in the array:

    js
    const a = Array.from({ length: 10 }, () =>
      Array.from({ length: 10 }, Math.random),
    ); / A 10×10 array of random numbers
    
    for (let i = 0, j = 9; i <= 9; i++, j--) {
      console.log(`a[${i}][${j}] = ${a[i][j]}`);
    }
    

    Using the comma operator to join assignments

    Because commas have the lowest precedence — even lower than assignment — commas can be used to join multiple assignment expressions. In the following example, a is set to the value of b = 3 (which is 3). Then, the c = 4 expression evaluates and its result becomes the return value of the entire comma expression.

    js
    let a, b, c;
    
    a = b = 3, c = 4; / Returns 4
    console.log(a); / 3 (left-most)
    
    let x, y, z;
    
    x = (y = 5, z = 6); / Returns 6
    console.log(x); / 6 (right-most)
    

    Processing and then returning

    Another example that one could make with the comma operator is processing before returning. As stated, only the last element will be returned but all others are going to be evaluated as well. So, one could do:

    js
    function myFunc() {
      let x = 0;
    
      return (x += 1, x); / the same as return ++x;
    }
    

    This is especially useful for one-line reduce() and one with map():

    js
    let sum = 0;
    const squares = [1, 2, 3, 4, 5].map((x) => ((sum += x), x * x));
    console.log(squares); / [1, 4, 9, 16, 25]
    console.log(sum); / 15
    

    Discarding reference binding

    The comma operator always returns the last expression as a value instead of a reference. This causes some contextual information such as the this binding to be lost. For example, a property access returns a reference to the function, which also remembers the object that it's accessed on, so that calling the property works properly. If the method is returned from a comma expression, then the function is called as if it's a new function value, and this is undefined.

    js
    const obj = {
      value: "obj",
      method() {
        console.log(this.value);
      },
    };
    
    obj.method(); / "obj"
    (obj.method)(); / "obj" (the grouping operator still returns the reference)
    (0, obj.method)(); / undefined (the comma operator returns a new value)
    

    You can enter indirect eval with this technique, because direct eval requires the function call to happen on the reference to the eval() function.

    js
    globalThis.isDirectEval = false;
    
    {
      const isDirectEval = true;
      console.log(eval("isDirectEval")); / true
      console.log((eval)("isDirectEval")); / true (the grouping operator still returns a reference to `eval`)
      console.log((0, eval)("isDirectEval")); / false (the comma operator returns a new value)
    }
    

    Specifications

    Specification
    ECMAScript® 2026 Language Specification
    # sec-comma-operator

    Browser compatibility

    See also