Destructuring, Spread & Rest

Unpack values into variables, and copy or merge arrays and objects with ...

Lesson 29 of 56Intermediate13 min read

Modern JavaScript has two small pieces of syntax that appear in almost every file: destructuring, which unpacks values from arrays and objects into separate variables, and the three dots ..., which either spread values out or gather them together.

Neither does anything you couldn't do the long way. Their value is in making code shorter and clearer, particularly when you work with objects from servers, function settings and copies of data. Once you recognise them, a lot of modern code becomes much easier to read.

Object destructuring

JavaScript
const user = { name: "Ivy", age: 28, city: "Leeds" };

const { name, city } = user;          // pick properties by name
const { age: years } = user;          // rename: age becomes years
const { role = "member" } = user;     // default if missing

The variable names must match the property names, unless you rename them with a colon. Destructuring is especially common in function parameters, as in function greet({ name }) { … }, which picks out just the property the function needs.

Array destructuring

JavaScript
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;   // by position
const [first, , third] = rgb;     // skip an item with a comma
let a = 1, b = 2;
[a, b] = [b, a];                  // swap two values

Array destructuring works by position rather than by name, so the order of the variables matters.

Spread: ... expands values

  • In arrays, [...a, ...b] combines two arrays and [...a] makes a copy.
  • In objects, { ...defaults, ...settings } merges them, with later properties winning. { ...user, age: 29 } copies an object with one change.
  • In function calls, Math.max(...numbers) passes the array's items as separate arguments.

Spread makes a shallow copy. The top level is new, but nested arrays and objects are still shared with the original, so changing one of them affects both copies.

Rest: ... gathers values

Rest uses the same three dots, but on the receiving side:

JavaScript
function sum(...nums) { … }             // all arguments in one array
const [winner, ...others] = players;    // the rest of the array
const { password, ...safeUser } = user; // everything except password

Rest must always come last, because it collects everything that's left over.

Destructuring in function parameters

Destructuring works directly in a function's parameter list, which makes functions that take an options object much easier to read and call:

JavaScript
function createUser({ name, role = "member", active = true } = {}) {
  return `${name} is a ${role}${active ? "" : " (inactive)"}`;
}
createUser({ name: "Ana", role: "admin" });

The caller passes one object and can list the options in any order, leaving out the ones they don't need. Defaults fill the gaps, and the final = {} means the function still works if it's called with no argument at all. You'll see this pattern in React components, configuration functions and many libraries.

Destructuring and Spread Syntax

Destructuring and spread

const { a, b: renamed, c = 0 } = obj;
const [x, y, ...others] = arr;
const copy = [...arr];
const merged = { ...obj1, ...obj2 };
function f(...args) { }

Destructuring and Spread Summary

  • Destructuring unpacks values from objects by name and from arrays by position.
  • You can rename properties and set default values while destructuring.
  • Spread (...) copies and merges arrays and objects, and passes array items as arguments.
  • Spread copies are shallow; nested values are still shared.
  • Rest (...) gathers remaining values and must come last.

Destructuring and Spread Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

Destructuring objects

const movie = {
  title: "Spirited Away",
  year: 2001,
  director: { name: "Hayao Miyazaki" },
};

const { title, year } = movie;
const { rating = "Not rated" } = movie;
const { director: { name: directorName } } = movie;

console.log(title, year);
console.log(rating);
console.log(directorName);
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 7Two variables from two properties in one line.
  2. Line 8A default value for a property that doesn't exist.
  3. Line 9Reach into a nested object and rename the result.
Example 2

Destructuring in function parameters

Very common in real code: destructure the object right in the parameter list.

function describe({ name, species, legs = 4 }) {
  return `${name} the ${species} has ${legs} legs`;
}

console.log(describe({ name: "Pip", species: "parrot", legs: 2 }));
console.log(describe({ name: "Rex", species: "dog" }));

const [winner, runnerUp, ...rest] = ["Ola", "Ben", "Cy", "Di"];
console.log(winner, runnerUp, rest);
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 1The function receives an object and unpacks it immediately, with a default for legs.
  2. Line 6Rex gets the default 4 legs.
  3. Line 8Array destructuring with rest gathers the remaining items.
Example 3

Spread for copies and merges

const defaults = { theme: "light", fontSize: 16, sound: true };
const userPrefs = { theme: "dark" };

const settings = { ...defaults, ...userPrefs };
console.log(settings);

const updated = { ...settings, fontSize: 18 };
console.log(settings.fontSize, updated.fontSize);

const week1 = [3, 5];
const week2 = [8, 1];
const all = [...week1, ...week2, 10];
console.log(all, Math.max(...all));

const { sound, ...visual } = settings;
console.log(visual);
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 4Merge objects. userPrefs comes last, so its theme wins.
  2. Line 7A copy with one change. The original is untouched.
  3. Line 12Combine arrays and add an extra value.
  4. Line 13Spread an array into separate arguments.
  5. Line 15Rest in destructuring: everything except sound.

Common Destructuring and Spread Mistakes

Spread copies are shallow

Don't
const a = { tags: ["x"] };
const b = { ...a };
b.tags.push("y");
console.log(a.tags); // ["x", "y"]: the nested array is shared!
Do
const b = { ...a, tags: [...a.tags] };
// or: const b = structuredClone(a);

Spread copies the top level only. Nested objects/arrays are still shared.

Destructuring from undefined

Don't
const { name } = undefined; // TypeError
Do
const { name } = user ?? {};

Destructuring and Spread in Real Projects

Destructuring in modern frameworks

React components receive props like function Card({ title, image }). State updates use spread: setUser({ ...user, name: "New" }). APIs return objects you destructure: const { data, error } = await fetchThing(). You'll see these patterns constantly.

Destructuring and Spread Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Pull out name and price, and combine the two arrays.

const product = { name: "Mug", price: 8 };
const { ,  } = product;
const all = [ a, b ];
Predict the outputmedium

What does this print?

const [a, , c = 9, d = 4] = [1, 2, 3];
console.log(a, c, d);
Predict the outputmedium

What does this print?

const base = { size: "M", color: "red" };
const order = { ...base, color: "blue", qty: 2 };
console.log(order.color, base.color);
Fix the bugmedium

average(…) should accept any number of arguments and return their average. average(2, 4, 6) should be 4. Fix the function.

function average(nums) {
  const total = nums.reduce((s, n) => s + n, 0);
  return total / nums.length;
}

console.log(average(2, 4, 6));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • average(2, 4, 6) is 4
  • average(10) is 10

Destructuring and Spread Quiz

3 questions to check what you learned.

  1. What does const [x, y] = [7, 8]; do?

    • Sets x to 7 and y to 8
    • Creates an array
    • Sets x and y to [7, 8]
    • Throws an error
  2. What does { ...a, ...b } do when both have a key id?

    • Throws an error
    • Keeps b's id (the later one wins)
    • Keeps a's id
    • Creates an array of both ids
  3. In function f(...args), what is args?

    • The first argument
    • A string
    • An object
    • An array of all the arguments

Destructuring and Spread Challenge

Safe user profile

Given user:

  1. Use object destructuring with rest to create publicProfile, containing everything except password
  2. Create updated as a copy of publicProfile with city changed to "Glasgow" (using spread)
  3. Destructure username from updated and log skye_r lives in Glasgow
const user = { username: "skye_r", password: "hunter2", city: "Dundee", age: 24 };
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • publicProfile has no password
  • updated has city Glasgow
  • publicProfile was not changed
  • Logs the sentence