Деструктуризация и spread
Зачем это нужно
С объектами и массивами постоянно приходится делать одно и то же: достать несколько полей в
переменные, скопировать, объединить два объекта, добавить элемент, не испортив оригинал.
Современный JavaScript делает это короткими записями — деструктуризацией и оператором ....
Их используют везде, особенно в React и при работе с данными от сервера.
Деструктуризация массива
«Разобрать» массив на переменные по порядку:
const point = [10, 20];
const [x, y] = point;
console.log(x, y);
const [first, , third] = ["а", "б", "в"]; // пропуск элемента — пустое место
console.log(first, third);
Вывод:
10 20
а в
Обмен значений без временной переменной:
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b);
Вывод:
2 1
Деструктуризация объекта
Из объекта переменные достаются по именам свойств:
const user = { name: "Аня", age: 15, city: "Худжанд" };
const { name, age } = user;
console.log(name, age);
const { city: town, country = "Таджикистан" } = user; // новое имя и значение по умолчанию
console.log(town, country);
Вывод:
Аня 15
Худжанд Таджикистан
Деструктуризация прямо в параметрах функции:
function hello({ name, age }) {
return `${name}, ${age} лет`;
}
console.log(hello({ name: "Тимур", age: 17, city: "Душанбе" }));
Вывод:
Тимур, 17 лет
Остаток ...rest
Три точки слева от = или в параметрах собирают «всё остальное»:
const [winner, ...others] = ["Аня", "Тимур", "Ира"];
console.log(winner, others);
const { password, ...safeUser } = { login: "anya", password: "123", age: 15 };
console.log(safeUser);
function sum(...nums) { // любое количество аргументов
return nums.reduce((s, n) => s + n, 0);
}
console.log(sum(1, 2, 3, 4));
Вывод:
Аня ["Тимур","Ира"]
{"login":"anya","age":15}
10
Spread ...
Те же три точки справа или в вызове «раскладывают» массив или объект:
const a = [1, 2];
const b = [3, 4];
console.log([...a, ...b, 5]); // объединение
console.log(Math.max(...[4, 9, 2])); // массив как отдельные аргументы
const base = { theme: "dark", lang: "ru" };
const mine = { ...base, lang: "tg" }; // копия с изменением
console.log(mine);
console.log(base);
Вывод:
[1,2,3,4,5]
9
{"theme":"dark","lang":"tg"}
{"theme":"dark","lang":"ru"}
При объединении объектов побеждает последнее значение: { ...base, lang: "tg" } перезаписывает lang.
Копия поверхностная!
const original = { name: "Аня", tags: ["js"] };
const copy = { ...original };
copy.name = "Ира"; // не влияет на оригинал
copy.tags.push("css"); // а это влияет!
console.log(original);
Вывод:
{"name":"Аня","tags":["js","css"]}
Spread копирует только верхний уровень. Вложенный массив tags остался общим — копия хранит ту же
ссылку. Чтобы изменить вложенное без порчи оригинала, копируют и его: { ...original, tags: [...original.tags, "css"] }.
Полную глубокую копию делает structuredClone(obj).
Сравнение объектов
console.log({ a: 1 } === { a: 1 });
const x = { a: 1 };
const y = x;
console.log(x === y);
Вывод:
false
true
=== для объектов и массивов сравнивает ссылки, а не содержимое: равны только если это один и
тот же объект.
Как это работает внутри
Деструктуризация — просто короткая запись. const { name, age } = user — это то же самое, что
const name = user.name; const age = user.age;. А { ...a, ...b } создаёт новый пустой объект и
по очереди копирует в него свойства a, затем b. Значения-объекты при этом не копируются — копируется
ссылка на них. Отсюда и «поверхностность».
Частые ошибки
- Перепутали скобки. Массив разбирают квадратными
[a, b] = arr, объект — фигурными{ a } = obj. - Имя не совпадает со свойством.
const { username } = { name: "Аня" }→undefined. Нужно{ name: username }. ...restне последним.const [...rest, last] = arr— ошибка: остаток всегда последний.- Думать, что spread копирует глубоко. Вложенные массивы и объекты остаются общими.
- Порядок при объединении.
{ lang: "tg", ...base }—langизbaseперезапишет твой.
Шпаргалка
| Что | Как |
|---|---|
| Разобрать массив | const [a, b] = arr; |
| Разобрать объект | const { name, age } = obj; |
| Переименовать / по умолчанию | const { city: town, x = 0 } = obj; |
| В параметрах | function f({ name }) { … } |
| Остаток | const [first, ...rest] = arr; |
| Любое число аргументов | function f(...args) { … } |
| Копия / объединение массивов | [...a], [...a, ...b] |
| Копия / объединение объектов | { ...o }, { ...o, key: 1 } |
| Глубокая копия | structuredClone(o) |