Spread и rest
Spread (...) раскрывает итерируемое. Rest (...) собирает в массив. Синтаксис один, но роль разная.
Spread в массивах
Копия
const copy = [...arr];
Поверхностная. Вложенные объекты — те же ссылки.
Объединение
const merged = [...a, ...b];
const withExtra = [0, ...arr, 10];
Замена методов
Старый способ:
Math.max.apply(null, [1, 2, 3]);
Новый:
Math.max(...[1, 2, 3]);
Преобразование
[...new Set([1, 2, 2, 3])]; // [1, 2, 3]
[...'abc']; // ['a', 'b', 'c']
[...map]; // итерация Map
Spread в объектах
Копия
const copy = { ...user };
Слияние
const merged = { ...a, ...b };
При конфликте — последний выигрывает:
const merged = { ...{ a: 1, b: 2 }, ...{ b: 3 } };
// { a: 1, b: 3 }
Обновление
const updated = { ...user, name: 'Боб' };
Перезапись
const override = { name: 'Боб', ...user }; // name из user
Spread в вызовах функций
function add(a, b, c) {
return a + b + c;
}
const args = [1, 2, 3];
add(...args);
Rest в параметрах
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
Несколько:
function log(level, ...messages) {
console.log(`[${level}]`, ...messages);
}
Первый — level, остальные — messages.
Rest в деструктуризации
const [first, ...rest] = [1, 2, 3, 4];
const { name, ...others } = user;
Rest — всегда последний.
Разница
Spread — раскрывает:
const arr = [1, ...other, 2];
Rest — собирает:
function fn(...args) {}
Синтаксис ... одинаковый, но место разное:
- В аргументах функции или в деструктуризации — rest
- В выражении (массив, объект, вызов) — spread
Полезные паттерны
Удаление элемента без мутации
const without = items.filter((i) => i !== 'x');
Или через slice
const [, ...rest] = [1, 2, 3]; // без первого
Исключение полей
const { password, ...safeUser } = user;
Обновление вложенного
const updated = {
...user,
address: {
...user.address,
city: 'Питер',
},
};
Массив объектов → объект
const indexed = Object.fromEntries(
users.map((u) => [u.id, u])
);
Поверхностная копия
spread не глубокий:
const user = { name: 'Алиса', address: { city: 'Москва' } };
const copy = { ...user };
copy.address.city = 'Питер';
user.address.city; // 'Питер' — тот же объект
Глубокая:
const deep = structuredClone(user);
Spread с Map и Set
const map = new Map([['a', 1], ['b', 2]]);
[...map]; // [['a', 1], ['b', 2]]
[...map.keys()]; // ['a', 'b']
[...map.values()]; // [1, 2]
const set = new Set([1, 2, 3]);
[...set]; // [1, 2, 3]
Не работает с объектами
[...{ a: 1 }]; // ошибка: объект не итерируемый
Только с итерируемыми: массивы, строки, Map, Set.
Итоги
- Spread раскрывает
- Rest собирает
- Spread для копий и слияний
- Rest для вариативных аргументов
- Поверхностная копия
structuredCloneдля глубокой