Что такое spread и rest операторы в JavaScript?
...) разворачивает итерируемый объект в отдельные элементы, а rest (...) собирает оставшиеся аргументы или элементы в массив. Синтаксис одинаковый, но смысл противоположный: spread — «расширить», rest — «собрать».Spread-оператор (...)
Spread разворачивает итерируемый объект (массив, строку, объект) в отдельные элементы в тех местах, где ожидается список значений.
Копирование и объединение массивов
const a = [1, 2, 3];
const b = [4, 5, 6];
// Объединение массивов
const merged = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
// Поверхностная копия
const copy = [...a]; // [1, 2, 3]
Передача аргументов в функцию
const numbers = [3, 1, 4, 1, 5];
console.log(Math.max(...numbers)); // 5
Копирование и объединение объектов
const defaults = { theme: 'light', lang: 'ru' };
const userSettings = { lang: 'en' };
// Более поздние свойства перезаписывают более ранние
const config = { ...defaults, ...userSettings };
// { theme: 'light', lang: 'en' }
Spread со строкой
const chars = [..,'hello']; // ['h', 'e', 'l', 'l', 'o']
Rest-оператор (...)
Rest собирает оставшиеся элементы в новый массив. Используется в параметрах функций и при деструктуризации.
В параметрах функции
function sum(first, ...rest) {
// rest — массив всех аргументов, кроме первого
return rest.reduce((acc, n) => acc + n, first);
}
console.log(sum(1, 2, 3, 4)); // 10
Важно: rest-параметр всегда должен быть последним в списке.
В деструктуризации массива
const [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]
В деструктуризации объекта
const { id, ...rest } = { id: 1, name: 'Alice', role: 'admin' };
console.log(id); // 1
console.log(rest); // { name: 'Alice', role: 'admin' }
Ключевые отличия
| Spread | Rest | |
|---|---|---|
| Направление | Разворачивает | Собирает |
| Контекст | Вызов функции, литерал массива/объекта | Параметры функции, деструктуризация |
| Позиция | Любая | Всегда последний |
Важные нюансы
- Spread и rest выполняют поверхностное копирование — вложенные объекты копируются по ссылке.
- Spread работает с любым итерируемым объектом (массив, Set, Map, строка), но не с обычными объектами в контексте массива.
arguments— псевдомассив, rest-параметр — настоящий массив с методамиmap,filterи т.д.
Что хочет услышать интервьюер
Понимание, что оба оператора имеют одинаковый синтаксис `...`, но работают в противоположных направлениях
Умение привести примеры spread в вызове функции и при создании массива/объекта
Знание, что rest-параметр должен быть последним и что он возвращает настоящий массив (в отличие от `arguments`)
Осознание, что копирование поверхностное — вложенные объекты копируются по ссылке
Практическое применение: слияние объектов, клонирование массивов, variadic-функции
Пример: Spread: клонирование и объединение
// Объединение массивов
const front: number[] = [1, 2, 3];
const back: number[] = [4, 5, 6];
const all: number[] = [...front, ...back];
console.log(all); // [1, 2, 3, 4, 5, 6]
// Слияние объектов (поздние свойства побеждают)
interface Config {
theme: string;
lang: string;
debug?: boolean;
}
const defaults: Config = { theme: 'light', lang: 'ru' };
const overrides: Partial<Config> = { lang: 'en', debug: true };
const config: Config = { ...defaults, ...overrides };
console.log(config); // { theme: 'light', lang: 'en', debug: true }
// Передача массива как аргументов
const nums = [3, 1, 4, 1, 5, 9];
console.log(Math.max(...nums)); // 9
Пример: Rest: сбор оставшихся аргументов
// Rest в параметрах функции
function logMessages(level: string, ...messages: string[]): void {
// messages — настоящий массив, есть forEach, map и т.д.
messages.forEach(msg => console.log(`[${level}] ${msg}`));
}
logMessages('INFO', 'Запуск', 'Подключение к БД', 'Готово');
// [INFO] Запуск
// [INFO] Подключение к БД
// [INFO] Готово
// Rest при деструктуризации массива
const [first, second, ...remaining] = [10, 20, 30, 40, 50];
console.log(first); // 10
console.log(second); // 20
console.log(remaining); // [30, 40, 50]
// Rest при деструктуризации объекта
const { id, ...userData } = { id: 42, name: 'Alice', role: 'admin' };
console.log(id); // 42
console.log(userData); // { name: 'Alice', role: 'admin' }
Типичные ошибки
Путают spread и rest: говорят, что это один оператор с одной функцией, не понимая контекстной разницы
Считают, что `{ ...obj }` делает глубокое клонирование — на самом деле вложенные объекты остаются по ссылке
Пытаются поставить rest-параметр не последним в списке параметров функции
Не знают, что spread можно применять к строкам и Set/Map, а не только к массивам
Смешивают rest-параметры и объект `arguments` — не знают, что `arguments` недоступен в стрелочных функциях


