Что такое spread и rest операторы в JavaScript?

JuniorJavaScript · Frontend·Обновлено 29 июня 2026
Коротко
Spread (...) разворачивает итерируемый объект в отдельные элементы, а 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` недоступен в стрелочных функциях

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.5
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее