Command Palette

Search for a command to run...

Hectal
PHASE 5Beginner ~24 min· topic 8 of 10

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
...name on the left side: collects the remaining items into a new array.
Spread
...arr on 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.

app.jswhole filejavascript
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;
// red = 255, green = 128, blue = 0

02Skip, default, collect

Commas skip, = gives a fallback, ... gathers the rest.

app.jswhole filejavascript
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).

app.jswhole filejavascript
let a = 1;
let b = 2;
[a, b] = [b, a]; // a = 2, b = 1

04Spread to copy and merge

Three dots inside [ ] pour the items of another array into the new one.

Spread to copy and mergediagram
Rendering diagram…

05Spread into a function call

Functions that take separate arguments, like Math.max, can be given an array this way.

app.jswhole filejavascript
const scores = [40, 95, 70];
Math.max(...scores); // 95, same as Math.max(40, 95, 70)

Try it yourself

  1. 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. 2

    Rotate three

    In the second example, add let p1 = "a", p2 = "b", p3 = "c"; and rotate them in one line so they become b c a.

  3. 3

    Insert in the middle

    In the third example, build [1, 2, "middle", 3, 4] from a and b with spread. Then do it with toSpliced and compare.

Code & diagrams

Destructuring: position, skip, default, rest ES2015+ New tab

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
null
Swap, return several values, split a string ES2015+ New tab

Click Swap: the same one-line swap runs on each click.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

2 1
1 9
2024 01 15
Spread: copy, merge, unpack ES2015+ New tab

Pushing 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 ]
10

Break 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];.

terminal
$ Console
── what you'll see ──
Uncaught ReferenceError: Cannot access 'right' before initialization

Break #2

Rest that isn't last

Write const [...start, last] = [1, 2, 3];.

terminal
$ Console
── what you'll see ──
Uncaught SyntaxError: Rest element must be last element

Break #3

Spreading a huge array into a call

Write Math.max(...bigArray) with a few hundred thousand numbers.

terminal
$ Console
── what you'll see ──
Uncaught RangeError: Maximum call stack size exceeded

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👍"].length is 2 while "a👍".length is 3.

Remember this

  1. 1

    Array destructuring (ES2015) creates variables from an array's items by position: const [x, y] = [10, 20]; makes x = 10 and y = 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 become undefined, so const [a, b] = [1] gives b = undefined.

  2. 2

    Defaults fill in when the item is undefined: const [size = "M"] = []; gives "M". A default is not used for null, only for undefined (including missing items). Defaults can use earlier variables: const [w, h = w] = [5]; makes a square.

  3. 3

    The rest element ...name collects all remaining items into a new array: const [head, ...tail] = [1, 2, 3]; gives head = 1, tail = [2, 3]. It must be last, and tail is always an array (empty if nothing is left). Rest parameters in functions (function sum(...nums), Phase 3) are the same idea for arguments.

  4. 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 then const [min, max] = minMax(nums);. React's const [count, setCount] = useState(0) uses exactly this.

  5. 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. 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

01

How does array destructuring work, and what happens to missing items?

02

How do you swap two variables in JavaScript without a temporary variable?

03

What is the difference between rest and spread?

04

How do you merge two arrays and remove duplicates?

Practice

01

Given const scores = [88, 72, 95, 60];, put the first score in top and the rest in others, and print both.

02

Write addToFront(arr, item) that returns a new array with item first, without changing arr.

03

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, push into 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.