The Spread Operator
Introduction
Spread syntax (...) expands an iterable into individual elements, or copies enumerable own properties from one object into another object literal. It is one of the most common tools for immutable updates in modern JavaScript.
The same three dots also appear in rest syntax, but the direction is opposite: spread expands, while rest collects.
Why This Matters
React state updates, Redux reducers, API payload composition, and interview coding exercises frequently rely on spread. Strong candidates know that spread is shallow, that array/function spread requires an iterable, and that object spread copies properties with later values overriding earlier ones.
Theory
Where spread is valid
Spread appears in three high-value places:
- Array literals —
[0, ...items, 99]inserts each item from an iterable. - Function calls —
fn(...args)passes each element as a separate argument. - Object literals —
{ ...base, role: 'admin' }copies enumerable own properties.
Spread is shallow
Spreading an array or object creates a new outer container, but nested objects are still shared references. { ...user } is not a deep clone. Mutating copy.profile.city also mutates user.profile.city if both point at the same nested object.
Override order
For object spread, properties on the right win: { ...defaults, timeout: 1000 } overrides defaults.timeout, while { timeout: 1000, ...defaults } lets defaults override your explicit value.
Spread vs rest
The syntax looks identical, but context decides meaning. On the right side of an assignment/call/literal, ... usually spreads values out. In parameter lists or destructuring patterns, ... collects values into one array/object.
Visual Diagrams
source: [1, 2, 3]
| | |
v v v
target: [0, ...source, 4]
result: [0, 1, 2, 3, 4]
For objects, later keys overwrite earlier keys:
{ ...defaults, timeout: 500 }Spread copies the outer level; it does not recursively clone nested values.
Code Examples
Array, call, and object spread
The same syntax expands values in arrays, function calls, and object literals.
Shallow copy caveat
Spread gives a new outer object, but nested references are reused.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1const original = { name: 'Ada', skills: ['JS'] };2const copy = { ...original, name: 'Grace' };3 4copy.skills.push('TS');5 6console.log(original.name);7console.log(original.skills.join(','));8console.log(copy.name);Predict the output #2
1const defaults = { retries: 2, mode: 'safe' };2const options = { retries: 5 };3 4const a = { ...defaults, ...options };5const b = { ...options, ...defaults };6 7console.log(a.retries);8console.log(b.retries);Coding Exercises
Merge unique tags without mutating inputs
EasyImplement mergeTags(base, extra) so it returns a new array with unique tags from both arrays in first-seen order. Do not mutate either input array.
Interview Questions
1Is object spread a deep clone?
No. Object spread creates a new outer object and copies enumerable own properties into it. If a property value is itself an object or array, the reference is copied, not deeply cloned. Nested mutation can still affect both objects.
2How is spread different from rest?
Spread expands values out of an iterable or object into another call/literal. Rest collects remaining values into one array or object inside a parameter list or destructuring pattern. Direction is the key mental model: spread expands, rest collects.
Follow-ups
- Where can spread syntax appear?
- What happens when object keys collide?
Quiz
1. What does `{ a: 1, ...{ a: 2, b: 3 } }` evaluate to?
2. Which statement about spread is false?
Summary
- Spread expands values in array literals, function calls, and object literals.
- Object spread copies enumerable own properties and applies overrides left to right.
- Spread is shallow; nested references remain shared.
- Remember the contrast: spread expands, rest collects.
Cheat Sheet
Array: [first, ...items, last].
Call: fn(...args).
Object: { ...base, override: true }.
Override order: rightmost key wins.
Caveat: shallow copy only; clone nested structures explicitly.