JavaScript Rest and Spread Syntax
In the realm of JavaScript, efficiency and elegance in coding are paramount. Two features that epitomize these qualities are Rest Parameters and Spread Syntax.
In JavaScript, the three-dot token ... does two opposite jobs depending on where you write it. As a function parameter it collects many arguments into a single array — that's a rest parameter. Everywhere else it spreads an iterable or object out into its individual pieces — that's spread syntax. Same symbol, mirror-image meaning.
Both were introduced in ES6 (2015). This page covers rest parameters (including the rule that they must come last), spread in function calls, array literals, and object literals, how to copy and merge with spread, how rest differs from spread, and why both beat the old arguments object.
Understanding Rest Parameters in JavaScript
A rest parameter lets a function accept an indefinite number of arguments and receive them as a real array. You write ... followed by a name; that name becomes an array holding every argument that wasn't matched by an earlier parameter.
Syntax and Usage
In the example below, numbers is an ordinary array, so you can call array methods like reduce directly on it — no conversion needed.
The Rest Parameter Must Be Last
A function can have only one rest parameter, and it must be the last one in the parameter list. Named parameters before it are filled first; the rest parameter then scoops up whatever remains. Putting it anywhere else is a SyntaxError.
Advantages Over the arguments Object
Before ES6, the only way to read all arguments was the special arguments object available inside non-arrow functions. Rest parameters are better in almost every way:
- A real array.
argumentsis array-like (it has alengthand indexes) but lacksmap,filter,reduce, etc. A rest parameter is a genuine array. - Explicit and readable. The signature
function sum(...numbers)tells the reader the function takes a variable list.argumentsis invisible in the signature. - You can name only the extras. Combine fixed parameters with a rest parameter, as shown above —
argumentsalways contains every argument, including the ones you already named. - Works with arrow functions. Arrow functions don't have their own
argumentsobject, so a rest parameter is the only way to gather variable arguments in an arrow function.
Dive into Spread Syntax
Spread syntax expands an iterable — an array, string, Set, Map, or any iterable — into its individual elements wherever a list of values is expected. The three contexts where you'll use it are function calls, array literals, and object literals.
Spread in Array Literals
Inside [ ], spread drops each element of an iterable into the new array. This is the cleanest way to insert one array into another at any position:
Because strings are iterable, spreading one produces an array of its characters:
Spread in Function Calls
In a function call, spread turns an array back into a list of separate arguments. This replaces the old func.apply(null, array) pattern:
Spread in Object Literals
Inside { }, spread copies an object's own enumerable properties into a new object. When keys collide, the later value wins — which makes spread perfect for applying overrides or defaults:
Copying and Merging
Spread is the idiomatic way to make a shallow copy or merge collections without mutating the originals:
Spread is shallow. It copies top-level values only. Nested objects and arrays are still shared by reference, so mutating a nested value affects both copies:
Rest vs Spread: Telling Them Apart
The ... token looks identical in both roles, so use the position to decide which one you're reading:
| Rest parameter | Spread syntax | |
|---|---|---|
| Where it appears | In a function's parameter list | In a call, array literal, or object literal |
| What it does | Gathers many values into one array | Expands one iterable/object into many values |
Side of the = | Left side (a destructuring target) | Right side (a value being produced) |
| Example | function f(...args) {} | f(...args) |
A simple test: if ...x is receiving values, it's rest; if it's producing values, it's spread.
Combining Rest Parameters and Spread Syntax
The two are mirror images, so they pair naturally — rest collects arguments into an array on the way in, and spread expands an array into arguments on the way out:
A common real-world pattern is a wrapper that forwards every argument to another function:
Destructuring with the Rest Pattern
In a destructuring assignment, the rest pattern captures whatever properties or elements you didn't name explicitly. In objects it produces an object of the leftover keys; in arrays, an array of the remaining items.
Conclusion
The ... token is one of the most useful additions ES6 made to JavaScript. As a rest parameter it gathers a variable number of arguments into a clean array (and replaces the awkward arguments object); as spread syntax it expands iterables into function calls, array literals, and object literals, giving you concise shallow copies and merges. Remember the two rules that trip people up most: a rest parameter must be the last parameter, and spread copies are shallow.
Related Topics
- Destructuring assignment — pull values out of arrays and objects, often paired with the rest pattern.
- JavaScript Array — the data structure rest parameters hand you and spread expands.
- Arrow functions revisited — why arrows rely on rest parameters instead of
arguments. - Function binding — controlling
this, frequently combined with spread when forwarding arguments.