Destructuring, Rest & Spread

JavaScript · Lesson 24 of 61 7 min read Updated

Modern JavaScript code is full of square and curly brackets on the left of an = sign, and of three dots ... in front of names. These are destructuring, rest and spread, three short syntaxes for taking data apart and putting it back together. Once you know them, you will read React, Node.js and most library code much more easily.

In this lesson you will unpack arrays and objects into variables, use defaults and renaming, collect the remaining items with rest, and copy and merge arrays and objects with spread.

Array destructuring

Destructuring means unpacking values from an array or object into separate variables in one line. For arrays, you write square brackets on the left of =, and variables are filled by position.

JavaScriptRun it yourself
const toppers = ["Meera", "Farhan", "Kabir", "Isha"];

const [first, second] = toppers;
console.log(first, second);

const [, , third] = toppers;
console.log(third);

const [winner, ...others] = toppers;
console.log(winner, others);

const [a, b, c, d, fifth = "No one"] = toppers;
console.log(fifth);
Output
Meera Farhan
Kabir
Meera [ 'Farhan', 'Kabir', 'Isha' ]
No one
  • [first, second] takes the first two items; the rest are ignored.
  • Empty places between commas skip items: [, , third] takes the third.
  • ...others is a rest element: it collects all remaining items into a new array. It must come last.
  • fifth = "No one" is a default value, used when there is no item at that position (or the item is undefined).

A neat trick: destructuring can swap two variables without a temporary variable.

JavaScriptRun it yourself
let left = "Chai";
let right = "Coffee";

[left, right] = [right, left];
console.log(left, right);
Output
Coffee Chai

Object destructuring

For objects, you write curly braces on the left, and variables are matched by key name, not by position.

JavaScriptRun it yourself
const booking = { pnr: "4521367890", passenger: "Ananya", coach: "B3", berth: 34 };

const { passenger, coach } = booking;
console.log(passenger, coach);

const { berth: seatNumber, meal = "Not booked" } = booking;
console.log(seatNumber, meal);

const { pnr, ...details } = booking;
console.log(pnr);
console.log(details);
Output
Ananya B3
34 Not booked
4521367890
{ passenger: 'Ananya', coach: 'B3', berth: 34 }
  • { passenger, coach } creates two variables with the same names as the keys. Order does not matter.
  • berth: seatNumber renames: it reads the berth property into a variable called seatNumber. Read the colon as "goes into".
  • meal = "Not booked" gives a default because booking has no meal.
  • ...details collects all the other properties into a new object.

You can also destructure nested data by repeating the pattern: const { customer: { city } } = order; reads order.customer.city into city. Keep nesting shallow, though; deep patterns are hard to read, and they throw if a middle level is missing.

Destructuring function parameters

This is where destructuring is used most. When a function takes several settings, pass one object and destructure it in the parameter list. Callers can then give the settings in any order and skip the ones that have defaults.

JavaScriptRun it yourself
function bookTicket({ from, to, travelClass = "SL", passengers = 1 }) {
  return `${passengers} x ${travelClass}: ${from} to ${to}`;
}

console.log(bookTicket({ from: "Jaipur", to: "Delhi" }));
console.log(bookTicket({ to: "Kochi", from: "Pune", travelClass: "3A", passengers: 2 }));
Output
1 x SL: Jaipur to Delhi
2 x 3A: Pune to Kochi

Compare this with bookTicket("Pune", "Kochi", "3A", 2), where a reader must remember what the third and fourth arguments mean. Named settings explain themselves.

Spread with arrays

The spread syntax ... does the opposite of rest: it expands an array (or any iterable) into separate values, right where you write it.

JavaScriptRun it yourself
const morning = ["Idli", "Dosa"];
const evening = ["Samosa", "Pakora"];

const menu = [...morning, "Thali", ...evening];
console.log(menu);

const copy = [...menu];
console.log(copy === menu);

const prices = [40, 120, 85];
console.log(Math.max(...prices));

console.log([..."PUNE"]);
Output
[ 'Idli', 'Dosa', 'Thali', 'Samosa', 'Pakora' ]
false
120
[ 'P', 'U', 'N', 'E' ]
  • [...a, ...b] joins arrays, and you can add items anywhere in between.
  • [...menu] makes a new array with the same items: a quick copy.
  • Math.max(...prices) passes each price as a separate argument, because Math.max() does not accept an array.
  • Spreading a string gives an array of its characters.

Spread with objects

Spread also works inside object literals. It copies all properties of one object into a new one. When two objects have the same key, the one written later wins.

JavaScriptRun it yourself
const defaults = { theme: "light", language: "English", fontSize: 16 };
const saved = { language: "Hindi", fontSize: 18 };

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

const darkSettings = { ...settings, theme: "dark" };
console.log(darkSettings.theme, settings.theme);
Output
{ theme: 'light', language: 'Hindi', fontSize: 18 }
dark light

This pattern, defaults first and the user's choices after, is very common. The last line shows how to "change" an object without touching the original: copy it and override one property. Frameworks such as React rely on this style of update.

Rest or spread?

Both use three dots. The position tells you which one it is:

Where the ... appearsNameWhat it does
Left of = in destructuringRestCollects remaining items or properties
In a function's parameter listRest parameterCollects remaining arguments into an array
Inside [ ] or { } on the rightSpreadExpands items or properties into the new array or object
Inside a function call's bracketsSpreadExpands an array into separate arguments

Rest parameters were introduced in Functions. In short: rest gathers, spread scatters.

Common mistakes

  • Destructuring undefined. const { city } = undefined; throws a TypeError. Give function parameters a default: function f({ a } = {}).
  • Rest not at the end. const [...rest, last] = list; is a syntax error. Rest must be last.
  • Wrong order when merging. { ...saved, ...defaults } lets the defaults overwrite the user's choices. Put the values that should win last.
  • Expecting a deep copy from spread. Nested arrays and objects are shared.
  • Confusing rename and default. { a: b } renames a to b; { a = 5 } gives a a default.

Key points

  • Array destructuring unpacks by position; object destructuring unpacks by key.
  • Use key: newName to rename and = value for defaults.
  • A rest element (...rest) collects what is left and must come last.
  • Destructured object parameters give functions clear, named, optional settings.
  • Spread (...) expands arrays into items or arguments and copies object properties; later keys win.
  • Spread copies are shallow.

Exercise

A student record arrives as { name: "Isha", marks: [78, 91, 66], city: "Rohtak", year: 2 }. Use object destructuring to get name and marks, and collect everything else into rest. Then use array destructuring to get the first mark and the remaining marks. Finally, create a new object that has all of the original properties plus year: 3, without changing the original, and print both years.

Show solution
JavaScript
const record = { name: "Isha", marks: [78, 91, 66], city: "Rohtak", year: 2 };

const { name, marks, ...rest } = record;
const [firstMark, ...otherMarks] = marks;

console.log(name, firstMark, otherMarks);
console.log(rest);

const promoted = { ...record, year: 3 };
console.log(record.year, promoted.year);
Output
Isha 78 [ 91, 66 ]
{ city: 'Rohtak', year: 2 }
2 3

Rest in object destructuring gathers city and year. Spread copies record and the later year: 3 overrides the copied value, so the original stays at year 2.

Quick Quiz

1. What is x after const [, x] = [10, 20, 30];?

2. What does const { price: cost } = { price: 99 }; create?

3. What is { ...{ a: 1, b: 2 }, b: 5 }?

4. Which call passes the numbers of list as separate arguments?

Learn JavaScript with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call