Destructuring and spread
Why it matters
With objects and arrays you constantly do the same things: pull several fields into variables, copy,
merge two objects, add an element without spoiling the original. Modern JavaScript does this with short
syntax — destructuring and the ... operator. They're used everywhere, especially in React and
when working with server data.
Array destructuring
"Unpack" an array into variables in order:
const point = [10, 20];
const [x, y] = point;
console.log(x, y);
const [first, , third] = ["a", "b", "c"]; // skipping an element — an empty slot
console.log(first, third);
Output:
10 20
a c
Swapping values without a temporary variable:
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b);
Output:
2 1
Object destructuring
Variables are taken from an object by property name:
const user = { name: "Anna", age: 15, city: "Khujand" };
const { name, age } = user;
console.log(name, age);
const { city: town, country = "Tajikistan" } = user; // a new name and a default value
console.log(town, country);
Output:
Anna 15
Khujand Tajikistan
Destructuring right in a function's parameters:
function hello({ name, age }) {
return `${name}, ${age} years old`;
}
console.log(hello({ name: "Timur", age: 17, city: "Dushanbe" }));
Output:
Timur, 17 years old
The rest ...rest
Three dots on the left of = or in parameters collect "everything else":
const [winner, ...others] = ["Anna", "Timur", "Ira"];
console.log(winner, others);
const { password, ...safeUser } = { login: "anna", password: "123", age: 15 };
console.log(safeUser);
function sum(...nums) { // any number of arguments
return nums.reduce((s, n) => s + n, 0);
}
console.log(sum(1, 2, 3, 4));
Output:
Anna ["Timur","Ira"]
{"login":"anna","age":15}
10
Spread ...
The same three dots on the right or in a call "spread out" an array or object:
const a = [1, 2];
const b = [3, 4];
console.log([...a, ...b, 5]); // combining
console.log(Math.max(...[4, 9, 2])); // an array as separate arguments
const base = { theme: "dark", lang: "en" };
const mine = { ...base, lang: "tg" }; // a copy with a change
console.log(mine);
console.log(base);
Output:
[1,2,3,4,5]
9
{"theme":"dark","lang":"tg"}
{"theme":"dark","lang":"en"}
When merging objects the last value wins: { ...base, lang: "tg" } overwrites lang.
The copy is shallow!
const original = { name: "Anna", tags: ["js"] };
const copy = { ...original };
copy.name = "Ira"; // doesn't affect the original
copy.tags.push("css"); // but this does!
console.log(original);
Output:
{"name":"Anna","tags":["js","css"]}
Spread copies only the top level. The nested tags array is still shared — the copy holds the same
reference. To change something nested without spoiling the original, copy it too:
{ ...original, tags: [...original.tags, "css"] }. A full deep copy is made by structuredClone(obj).
Comparing objects
console.log({ a: 1 } === { a: 1 });
const x = { a: 1 };
const y = x;
console.log(x === y);
Output:
false
true
=== for objects and arrays compares references, not contents: they're equal only if it's the very same object.
How it works inside
Destructuring is just shorthand. const { name, age } = user is the same as
const name = user.name; const age = user.age;. And { ...a, ...b } creates a new empty object and
copies into it the properties of a, then b. Values that are objects aren't copied — the reference to
them is copied. Hence the "shallowness".
Common mistakes
- Mixed-up brackets. An array is unpacked with square brackets
[a, b] = arr, an object with curly ones{ a } = obj. - The name doesn't match the property.
const { username } = { name: "Anna" }→undefined. You need{ name: username }. ...restnot last.const [...rest, last] = arris an error: the rest is always last.- Thinking spread copies deeply. Nested arrays and objects stay shared.
- Order when merging.
{ lang: "tg", ...base }—langfrombaseoverwrites yours.
Cheat sheet
| What | How |
|---|---|
| Unpack an array | const [a, b] = arr; |
| Unpack an object | const { name, age } = obj; |
| Rename / default | const { city: town, x = 0 } = obj; |
| In parameters | function f({ name }) { … } |
| Rest | const [first, ...rest] = arr; |
| Any number of arguments | function f(...args) { … } |
| Copy / combine arrays | [...a], [...a, ...b] |
| Copy / merge objects | { ...o }, { ...o, key: 1 } |
| Deep copy | structuredClone(o) |