ES6+beginner
Spread and Rest Operators
The three-dot syntax that expands an iterable into individual elements (spread) or collects multiple elements into a single array (rest), depending on context.
The same three dots do opposite things depending on where they appear.
Spread is like pouring an entire box's contents into a bigger box you're filling. Rest is the reverse: sweeping up whatever's left after everyone's grabbed their labeled item into one catch-all box.
Key Concepts
1
spread expands an iterable into individual items
rest collects individual items into an array2
const copy = [...arr]; // spread
function f(...args) { } // rest
const [first, ...others] = arr; // rest
f(...arr); // spread3
The rule: rest gathers on the left of an assignment or in a parameter list. Spread scatters everywhere
else.Arrays.
4
[...a, ...b] concatenate
[...new Set(a)] deduplicate
[...a].sort() sort a copy, not the original
[...'hello'] ['h','e','l','l','o']
Math.max(...numbers) pass an array as arguments5
Objects (ES2018).
6
{ ...defaults, ...options } later wins
{ ...obj, id: 5 } override one field
const { id, ...rest } = obj; omit one field7
That last pattern — destructuring with rest — is the standard way to remove a property without mutating.
8
Both are shallow.
const copy = { ...orig };
copy.nested === orig.nested; // true -- still shared9
Which is the most common misunderstanding: spread copies the top level only.
10
Object spread only copies own enumerable properties. Getters are evaluated and become plain values;
prototype methods are not copied at all. Spreading a class instance gives you a plain object with its data
and none of its behaviour.
11
Spread works on any iterable; object spread works on anything.
[...{ a: 1 }] TypeError -- not iterable
{ ...[1, 2] } { 0: 1, 1: 2 } -- indices as keys
{ ...'ab' } { 0: 'a', 1: 'b' }12
Rest must be last.
function f(...args, last) { } SyntaxError
const [...rest, last] = arr; SyntaxError13
One performance note. Spreading in a loop is quadratic:
14
// O(n²) -- a new array each iteration
items.reduce((acc, x) => [...acc, x], []);15
// O(n)
items.reduce((acc, x) => { acc.push(x); return acc; }, []);16
Fine for small arrays, and a real problem at a few thousand items.
17
What the interviewer is probing.1. "Same syntax — what distinguishes them?" Probing: position. Stalls: "They are the same."
Moves up: rest gathers on the left of an assignment or in a parameter list; spread expands on the
right or in a call.
18
2. "How deep does spread copy?" Probing: the depth. Stalls: "Fully." Moves up: one level —
nested objects remain shared references.
19
3. "What happens spreading a string?" Probing: iterables. Stalls: "An error." Moves up: it
becomes an array of characters, because strings are iterable — and it handles surrogate pairs better
than split("").
20
4. "What order wins when spreading two objects?" Probing: the merge rule. Stalls: "The
first." Moves up: later properties overwrite earlier ones, which is how defaults-then-overrides is
written.