🌱BeginnerModern JavaScript (ES6+)
Spread and Rest Operators
The ... syntax for expanding arrays/objects and collecting remaining values.
Overview
The three-dot syntax (...) serves two opposite but related purposes: spread expands an iterable into individual items, while rest collects multiple items into an array or object. The same punctuation, determined entirely by context.
Spread is used to: copy an array (avoiding mutation), merge arrays, copy/merge objects, pass array items as function arguments, and clone objects with overrides. It is a cleaner, more expressive alternative to methods like concat() and Object.assign().
Rest is used to: collect all remaining function arguments into an array (replacing the legacy arguments object), and gather remaining properties during destructuring. Rest parameters must always be last in a parameter list.
Key Points
- •Spread in array: [...arr] creates a shallow copy; [...a, ...b] merges arrays
- •Spread in object: { ...obj } copies properties; { ...obj, key: val } copies and overrides
- •Spread in function call: fn(...arr) passes array items as separate arguments
- •Rest in function params: function f(a, b, ...rest) rest gets all remaining args as an array
- •Rest in destructuring: const { a, ...others } = obj others has everything except a
- •Both create shallow copies nested objects/arrays are still shared references
Examples
Spread for copying and merging arrays
const a = [1, 2, 3];
const b = [4, 5, 6];
const copy = [...a]; // shallow copy
const merged = [...a, ...b]; // merge
const withExtra = [...a, 99, ...b]; // interleave
console.log(copy); // [1, 2, 3]
console.log(merged); // [1, 2, 3, 4, 5, 6]
console.log(withExtra);// [1, 2, 3, 99, 4, 5, 6]Spread for copying and overriding objects
const defaults = { theme: "light", lang: "en", font: "sans" };
const userPrefs = { lang: "fr", font: "serif" };
// Merge: later properties win
const config = { ...defaults, ...userPrefs };
console.log(config);
// { theme: "light", lang: "fr", font: "serif" }
// Add a single override
const withTitle = { ...config, title: "Dashboard" };
console.log(withTitle.title); // "Dashboard"This pattern (spread + override) is the standard way to do immutable object updates in React.
Rest parameters collect remaining arguments
function sum(first, ...rest) {
console.log("first:", first);
console.log("rest:", rest);
return first + rest.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // first:1 rest:[2,3,4] → 10
console.log(sum(5)); // first:5 rest:[] → 5Common Mistakes
- Treating spread as a deep clone { ...obj } only copies one level; nested objects are still shared
- Putting rest parameters anywhere but last: function f(...a, b) is a SyntaxError
- Confusing Object spread with Object.assign { ...a, ...b } is equivalent to Object.assign({}, a, b)
Note
In React, you'll see the spread pattern constantly for updating state: setState({ ...currentState, updatedField: newValue }). Understanding spread makes React code much easier to read.
Exercises
Write JavaScript code to solve each exercise. Run it and check your output.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4