Topic 5.8
Destructuring and Spread with Arrays
In one line
Array destructuring unpacks items into variables by position (const [a, b] = arr), with skipping, defaults and a ...rest to collect the remainder; spread (...arr) does the opposite, unpacking an array into a new array or a function call, which is how you copy and merge arrays.
Think of it like this
Unpacking a lunch box with three compartments. You take out the first thing and call it "sandwich", the second "apple", and you leave the third one in the box: that's destructuring. Tipping two lunch boxes out onto one big tray, side by side, is spread. "Give me the sandwich, and put everything else in this bag" is rest.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Destructuring
- Pulling items out of an array (or object) into separate variables in one statement.
- Default value
- A fallback used when the item is missing or
undefined. - Rest element
...nameon the left side: collects the remaining items into a new array.- Spread
...arron the right side or in a call: unpacks the items one by one.- Swap
- Exchange the values of two variables.
- Shallow copy
- A new outer array whose items are the same values (and the same inner objects) as the original.
- Merge
- Combine two or more arrays into one.
Step by step
01Unpack by position
The first name gets index 0, the second gets index 1, and so on.
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;
// red = 255, green = 128, blue = 002Skip, default, collect
Commas skip, = gives a fallback, ... gathers the rest.
const [, second] = ["a", "b", "c"]; // "b"
const [x = 0, y = 0] = [5]; // 5, 0
const [top, ...others] = [9, 8, 7]; // 9, [ 8, 7 ]03Swap
Build a new array on the right, unpack on the left. Start the line with a semicolon if the previous line has none (see Break it).
let a = 1;
let b = 2;
[a, b] = [b, a]; // a = 2, b = 104Spread to copy and merge
Three dots inside [ ] pour the items of another array into the new one.
05Spread into a function call
Functions that take separate arguments, like Math.max, can be given an array this way.
const scores = [40, 95, 70];
Math.max(...scores); // 95, same as Math.max(40, 95, 70)Try it yourself
- 1
Grab the last two
In the first example, use rest to get everything except the first item, then take the last item of that with
at(-1). Predict the values first. - 2
Rotate three
In the second example, add
let p1 = "a", p2 = "b", p3 = "c";and rotate them in one line so they becomeb c a. - 3
Insert in the middle
In the third example, build
[1, 2, "middle", 3, 4]fromaandbwith spread. Then do it withtoSplicedand compare.
Code & diagrams
The default only replaces `undefined`, so `null` stays `null`.
Console
(nothing was printed)Expected console output
10 20
10 30
0
10 [ 20, 30 ]
1 undefined
nullClick Swap: the same one-line swap runs on each click.
Preview
Console
Nothing logged yet.Expected console output
2 1
1 9
2024 01 15Pushing to `copy` didn't touch `a`. `sum(...merged)` spreads the array into arguments, and the rest parameter `...nums` collects them back into an array.
Console
(nothing was printed)Expected console output
[ 1, 2, 3, 4 ] [ 0, 1, 2, 2.5, 3, 4, 5 ]
[ 1, 2 ] [ 1, 2, 99 ]
4
[ 'h', 'e', 'y' ]
[ 1, 2, 3 ]
10Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
A swap after a line with no semicolon
Write let right = "R" (no semicolon) and on the next line [left, right] = [right, left];.
Break #2
Rest that isn't last
Write const [...start, last] = [1, 2, 3];.
Break #3
Spreading a huge array into a call
Write Math.max(...bigArray) with a few hundred thousand numbers.
Myth vs fact
Myth
[...arr] makes a full independent copy.
Fact
It copies the outer array only. Objects and arrays inside are shared with the original (Topic 5.10).
Myth
Defaults in destructuring replace null.
Fact
Only undefined (or a missing item) triggers the default. const [x = 1] = [null] gives null.
Myth
Rest and spread are different features with different syntax.
Fact
Both are .... On the receiving side (left of =, parameter lists) it collects into an array; on the giving side (array literals, calls) it unpacks.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Array destructuring uses the iterator protocol, so it works on any iterable (
const [a, b] = new Set([1, 2])), and also means it's a little slower than index access on hot paths. Object destructuring (Phase 6) uses property lookup instead. - ▸
You can destructure nested arrays and use destructuring in parameters and loops:
for (const [key, value] of Object.entries(obj)),function draw([x, y]) { ... }. - ▸
The exact limit on argument count for spread calls depends on the engine and stack size (often around 100,000 or more in V8). Don't rely on it; use a loop for unbounded data.
- ▸
Spreading a string splits by code points, not UTF-16 units, so emoji stay whole:
[..."a👍"].lengthis 2 while"a👍".lengthis 3.
Remember this
- 1
Array destructuring (ES2015) creates variables from an array's items by position:
const [x, y] = [10, 20];makesx = 10andy = 20. The left side looks like an array but is really a list of variable names. Skip items with an empty slot:const [first, , third] = arr;. Missing items becomeundefined, soconst [a, b] = [1]givesb = undefined. - 2
Defaults fill in when the item is
undefined:const [size = "M"] = [];gives"M". A default is not used fornull, only forundefined(including missing items). Defaults can use earlier variables:const [w, h = w] = [5];makes a square. - 3
The rest element
...namecollects all remaining items into a new array:const [head, ...tail] = [1, 2, 3];giveshead = 1,tail = [2, 3]. It must be last, andtailis always an array (empty if nothing is left). Rest parameters in functions (function sum(...nums), Phase 3) are the same idea for arguments. - 4
Swapping two variables needs no temporary variable:
[a, b] = [b, a];. The right side builds a new array from the old values, then the left side unpacks it. Destructuring also makes functions that "return several values" neat:return [min, max];and thenconst [min, max] = minMax(nums);. React'sconst [count, setCount] = useState(0)uses exactly this. - 5
Spread
...arr(ES2015) unpacks an iterable's items in place. Inside an array literal it builds a new array:[...a]is a copy,[...a, ...b]merges,[0, ...a, 99]adds items around. Inside a function call it passes items as separate arguments:Math.max(...nums). It works on any iterable:[..."hey"]gives letters,[...new Set(arr)]removes duplicates. - 6
Spread copies are shallow: the new array is new, but objects inside it are shared with the original (Topic 5.10). The same three dots mean rest on the left of
=or in a parameter list (collect), and spread on the right or in a call (unpack).
Explain it without notes
How does array destructuring work, and what happens to missing items?
How do you swap two variables in JavaScript without a temporary variable?
What is the difference between rest and spread?
How do you merge two arrays and remove duplicates?
Practice
Given const scores = [88, 72, 95, 60];, put the first score in top and the rest in others, and print both.
Write addToFront(arr, item) that returns a new array with item first, without changing arr.
Use destructuring to get the hours and minutes as numbers from the string "09:45".
Trade-offs
- ↔
Destructuring makes code shorter and names values clearly, but positional destructuring of long arrays (
const [, , , x]) is hard to read; return an object when there are more than two or three values. - ↔
Spread copies and merges are clear and immutable; for very large arrays or many repeated merges,
pushinto one array is faster and avoids argument-count limits.
Done when you can
I can destructure an array with skipping, defaults and rest.
I can swap two variables in one line.
I can copy and merge arrays with spread.
I can spread an array into a function call.
I can tell rest from spread by where the
...appears.