JavaScriptArray Destructuring

Array Destructuring

Array destructuring is a piece of ES2015 syntax that lets you pull elements out of an array (or any iterable) and bind them to variables in one statement. It is one of those features that looks like sugar and quickly becomes essential — once you start writing const [a, b] = pair, pair[0] / pair[1] feels clumsy.

The basics

Use square brackets on the left of an assignment. The pattern is matched against the array on the right; each name in the pattern receives the element at the same position.

JS
const colors = ["red", "green", "blue"];

const [first, second, third] = colors;
// first = "red", second = "green", third = "blue"

// Skip elements with a hole
const [, , onlyThird] = colors;
// onlyThird = "blue"

// Fewer names than elements — the rest are ignored
const [a] = colors;
// a = "red"

// More names than elements — extras are undefined
const [x, y, z, w] = ["one", "two"];
// w = undefined
Default values

If an element is missing or undefined, the default kicks in. null does not trigger the default — only undefined.

JS
const [a = 1, b = 2, c = 3] = [10, undefined];
// a = 10, b = 2 (default fired), c = 3 (missing)

const [x = "hi"] = [null];
// x = null  — null is a real value, not "missing"
The swap idiom

Swapping two variables without a temporary is the canonical example: it reads exactly like its meaning.

JS
let a = 1;
let b = 2;

[a, b] = [b, a];

console.log(a, b);   // 2 1
2 1
It works for any rearrangement
You can rotate three variables (`[a, b, c] = [c, a, b]`) or reverse a small fixed array the same way. For large rotations, prefer `.reverse()` or a temporary.
Nested destructuring

Patterns nest. You can pull elements out of arrays-of-arrays and even mix in object destructuring.

JS
const point = [10, [20, 30]];
const [x, [y, z]] = point;
// x = 10, y = 20, z = 30

// Mixing with objects
const users = [
  { name: "Ada", roles: ["admin", "editor"] },
  { name: "Lin", roles: ["viewer"] },
];

const [{ name: firstName, roles: [primaryRole] }] = users;
// firstName = "Ada", primaryRole = "admin"
Rest in destructuring

A trailing ...rest pattern collects everything that was not destructured into a new array. It must be the last element in the pattern.

JS
const [head, ...tail] = [1, 2, 3, 4, 5];
// head = 1, tail = [2, 3, 4, 5]

const [, ...withoutFirst] = ["a", "b", "c"];
// withoutFirst = ["b", "c"]

// SyntaxError — rest must be last
// const [...rest, last] = [1, 2, 3];
Rest creates a new array
The captured rest is a fresh array, not a view into the original. Mutating `tail` does not affect the source.
Works on any iterable

Array destructuring is really iterable destructuring. Strings, Map, Set, generators — anything with a [Symbol.iterator] works.

JS
const [first, second] = "hi";
// first = "h", second = "i"

const m = new Map([["a", 1], ["b", 2]]);
for (const [key, value] of m) {
  console.log(key, value);
}

// Generators
function* counter() { yield 10; yield 20; yield 30; }
const [a, b] = counter();
// a = 10, b = 20
Destructuring in function parameters

You can destructure right in a parameter list. It is especially handy with callbacks that pass arrays — Map.entries, Object.entries, .map((item, i) => ...).

JS
const pairs = [["a", 1], ["b", 2], ["c", 3]];

pairs.forEach(([key, value]) => {
  console.log(key, "=", value);
});

// With a default for the whole parameter
function greet([first = "there", last = ""] = []) {
  return `Hello, ${first} ${last}`.trim();
}

greet(["Ada", "Lovelace"]);   // "Hello, Ada Lovelace"
greet();                       // "Hello, there"
Common pitfalls
  • Destructuring null or undefined throws — const [a] = null is a TypeError. Pair with a fallback const [a] = arr ?? [].

  • Skipped slots still consume positions — [, b] means "skip first, take second", not "take first under the name b".

  • Default values are evaluated lazily — const [a = expensive()] = [1] does not call expensive because a was provided.

  • A trailing comma in a pattern does not change anything — [a, b,] is the same as [a, b].

The next page looks at the closely related ... spread operator and how it powers cloning, merging and rest-arguments in array contexts.