In short
Destructuring, spread and rest in JavaScript let you unpack values from arrays and objects, copy and merge them, and collect extra arguments, all with short modern syntax. What is destructuring in JavaScript?
Destructuring, spread and rest in JavaScript let you unpack values from arrays and objects, copy and merge them, and collect extra arguments, all with short modern syntax.
What is destructuring in JavaScript?
Destructuring means pulling values out of an array or object and saving them into variables in one step. Think of unpacking a grocery bag: instead of reaching in again and again, you take everything out and put each item on the shelf at once.
Array destructuring
With arrays, you use square brackets on the left side of =. Variables are filled by position.
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;
console.log(red, green, blue);
// Output: 255 128 0
const [first, , third] = ["gold", "silver", "bronze"];
console.log(first, third);
// Output: gold bronze
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b);
// Output: 2 1
A blank space between commas skips an item. The last example shows a neat trick: swapping two variables without a temporary variable.
Object destructuring, renaming and default values
With objects, you use curly braces, and variables are matched by key name, not position.
const user = {
name: "Kai",
email: "kai@example.com",
role: "editor",
};
const { name, email } = user;
console.log(name, email);
// Output: Kai kai@example.com
const { role: userRole } = user;
console.log(userRole);
// Output: editor
const { theme = "light", name: displayName = "Guest" } = user;
console.log(theme, displayName);
// Output: light Kai
Here is what each part does:
{ name, email }creates variables named after the keys.{ role: userRole }readsrolebut stores it in a variable calleduserRole. This is renaming.{ theme = "light" }gives a default value when the property is missing orundefined.userhas notheme, so it becomes"light".- You can combine renaming and a default:
name: displayName = "Guest".
Destructuring function parameters
This is one of the most useful patterns. When a function takes an options object, you can destructure it right in the parameter list. Defaults make the options optional.
const formatPrice = ({ amount, currency = "USD", decimals = 2 }) => {
return `${amount.toFixed(decimals)} ${currency}`;
};
console.log(formatPrice({ amount: 19.5 }));
// Output: 19.50 USD
console.log(formatPrice({ amount: 7, currency: "EUR", decimals: 0 }));
// Output: 7 EUR
The caller passes one object, and the function picks out the values it needs. The order of keys does not matter, which makes calls easy to read.
Common mistake: Destructuring
undefined. If someone callsformatPrice()with no argument, you get a TypeError. Add a default for the whole parameter:({ amount = 0, currency = "USD" } = {}) => ....
How to use the spread operator with arrays and objects
The spread syntax ... spreads the items of an array, or the properties of an object, into a new one. It is perfect for copying and merging without changing the originals.
const basics = ["HTML", "CSS"];
const skills = [...basics, "JavaScript"];
console.log(skills);
// Output: ["HTML", "CSS", "JavaScript"]
const defaults = { theme: "light", fontSize: 16, sound: true };
const userPrefs = { theme: "dark" };
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// Output: { theme: "dark", fontSize: 16, sound: true }
const updatedUser = { ...user, role: "admin" };
console.log(updatedUser.role, user.role);
// Output: admin editor
When you merge objects, later properties win. That is why theme is "dark": userPrefs comes after defaults. The last example creates an updated copy of user while the original stays the same, a pattern used a lot in modern frameworks.
You can also spread an array into a function call: Math.max(...[3, 9, 4]) returns 9.
Rest parameters: collect the remaining values
Rest uses the same three dots, but does the opposite job: it collects several values into one array. Use it in function parameters to accept any number of arguments, or in destructuring to grab "everything else".
const sum = (...numbers) => numbers.reduce((total, n) => total + n, 0);
console.log(sum(5, 10, 15));
// Output: 30
const [winner, ...others] = ["Zoe", "Max", "Lin"];
console.log(winner, others);
// Output: Zoe ["Max", "Lin"]
const { password, ...safeUser } = { id: 7, name: "Ivy", password: "secret" };
console.log(safeUser);
// Output: { id: 7, name: "Ivy" }
The last line is a handy way to remove a sensitive field before showing or sending data. A rest element must always come last.
Tip: Easy rule:
...on the right side of=or in a function call is spread (it expands)....on the left side or in a parameter list is rest (it collects).
Shallow copies and structuredClone
Spread makes a shallow copy. Only the top level is copied. Nested objects and arrays are still shared between the original and the copy.
const profile = { name: "Rae", address: { city: "Rome" } };
const shallow = { ...profile };
shallow.address.city = "Milan";
console.log(profile.address.city);
// Output: Milan (the original changed too!)
const deep = structuredClone(profile);
deep.address.city = "Turin";
console.log(profile.address.city);
// Output: Milan (the original is safe)
structuredClone() is built into all modern browsers and makes a deep copy, copying every level. Use it when your data is nested. It cannot copy functions, so it suits plain data like settings or API results.
Practice exercise
Given const movie = { title: "Up", year: 2009, ratings: [8, 9, 7] };:
- Destructure
titleandyear, renamingyeartoreleaseYear. - Destructure the first rating into
firstRatingand the rest intootherRatings. - Create
updatedMovie, a copy ofmoviewithyearset to2010and a newgenreproperty. - Write a function
average(...nums)and call it with the ratings spread in.
Hint: For step 2, destructure movie.ratings with [firstRating, ...otherRatings]. For step 4, call average(...movie.ratings).
Key takeaways
- Destructuring unpacks arrays by position and objects by key name.
- You can rename (
role: userRole) and set defaults (theme = "light") while destructuring. - Spread
...copies and merges arrays and objects; later object properties win. - Rest
...collects remaining values into an array or object and must come last. - Spread copies are shallow; use
structuredClone()for a deep copy of nested data.