Spread - это использование ... для раскрытия значений.
Если говорить просто, spread берёт одно значение и “раскладывает” его на отдельные элементы или свойства.
Именно поэтому его часто используют при вызове функций, копировании массивов, объединении массивов и объектов.
Синтаксис
Базовая идея выглядит так:
...value
Но сам по себе spread не используется где угодно. Обычно он встречается в трёх местах:
- при вызове функции
- в массивах
- в объектах
Что делает spread
Spread раскрывает содержимое значения наружу.
Например, массив:
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3
Здесь массив не передаётся как один объект целиком. Его элементы раскрываются по отдельности.
Spread при вызове функции
Это один из самых частых сценариев.
const numbers = [5, 10, 20];
console.log(Math.max(...numbers)); // 20
Без spread функция получила бы один массив вместо отдельных аргументов.
const numbers = [5, 10, 20];
// Math.max(numbers); // NaN
Math.max() ждёт список чисел, а не массив. Spread как раз помогает передать массив как набор аргументов.
Spread в массивах
Внутри массива spread раскрывает элементы другого массива или другого итерируемого значения.
const first = [1, 2];
const second = [3, 4];
const result = [...first, ...second];
console.log(result); // [1, 2, 3, 4]
Это очень удобно для объединения массивов.
Копия массива через spread
Spread часто используют для поверхностного копирования массива.
const original = [1, 2, 3];
const copy = [...original];
console.log(copy); // [1, 2, 3]
console.log(copy === original); // false
Получается новый массив, но элементы внутри пока те же самые по значению или по ссылке.
Добавление элементов в новый массив
Spread удобно комбинируется с обычными значениями.
const numbers = [2, 3];
const result = [1, ...numbers, 4];
console.log(result); // [1, 2, 3, 4]
Это читается проще, чем ручная сборка через цикл.
Spread работает не только с массивами
В массивах и при вызове функции spread хорошо работает с итерируемыми значениями, например со строками.
const chars = [..."JS"];
console.log(chars); // ["J", "S"]
Можно использовать и Set:
const uniqueNumbers = new Set([1, 2, 2, 3]);
console.log([...uniqueNumbers]); // [1, 2, 3]
Spread в объектах
В объектах spread копирует собственные перечисляемые свойства.
const user = { name: "Анна", age: 25 };
const copy = { ...user };
console.log(copy); // { name: "Анна", age: 25 }
Это удобный способ быстро создать новый объект на основе существующего.
Объединение объектов
Spread особенно часто используют для объединения объектов.
const user = { name: "Анна" };
const extra = { role: "admin" };
const result = { ...user, ...extra };
console.log(result); // { name: "Анна", role: "admin" }
Такой код очень часто встречается в современном JavaScript и особенно в React-коде.
Если свойства повторяются
Если одно и то же свойство встречается несколько раз, побеждает последнее значение.
const user = { name: "Анна", role: "user" };
const updated = { ...user, role: "admin" };
console.log(updated); // { name: "Анна", role: "admin" }
Это полезно для обновления отдельных полей без мутации исходного объекта.
Поверхностная копия, а не глубокая
Это очень важный момент.
Spread делает только поверхностную копию.
const user = {
name: "Анна",
address: { city: "Москва" },
};
const copy = { ...user };
copy.address.city = "Казань";
console.log(user.address.city); // "Казань"
Вложенный объект address не был скопирован глубоко. Скопировалась только верхняя структура.
То же самое касается вложенных массивов и объектов внутри массива.
Чем spread отличается от rest
И spread, и rest используют ..., поэтому их часто путают.
Но идея противоположная:
- spread раскрывает одно значение в несколько
- rest собирает несколько значений в одно
Spread:
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3
Rest:
function sum(...numbers) {
console.log(numbers); // [1, 2, 3]
}
Если ... стоит в параметрах функции, это обычно rest.
Если ... стоит в вызове функции, массиве или объекте, это spread.
Когда это полезно
Spread особенно удобен, когда:
- нужно передать массив как набор аргументов
- нужно объединить массивы
- нужно сделать копию массива или объекта
- нужно обновить объект без изменения исходного значения
- нужно добавить элементы в новый массив или свойства в новый объект
Пример:
function greet(name, city) {
console.log(`Привет, ${name} из ${city}!`);
}
const userData = ["Анна", "Москва"];
greet(...userData);
Частые ошибки
Путать spread и rest
function sum(...numbers) {
return numbers;
}
Здесь ...numbers в параметрах - это rest, а не spread.
Думать, что spread делает глубокую копию
const user = {
profile: { age: 25 },
};
const copy = { ...user };
Вложенные объекты и массивы всё ещё могут ссылаться на те же данные.
Использовать spread там, где значение не раскрывается таким образом
Например, обычный объект нельзя просто так раскрыть в аргументы функции или в массив:
const user = { name: "Анна" };
// console.log(...user); // TypeError
// const arr = [...user]; // TypeError
Обычный объект не является итерируемым значением.
Но в объекте spread с ним работает нормально:
const copy = { ...user };
Забывать, что последнее свойство перезаписывает предыдущее
const result = { name: "Анна", ...{ name: "Игорь" } };
console.log(result); // { name: "Игорь" }
Порядок здесь важен.
Ожидать, что spread изменит исходный массив или объект
const numbers = [1, 2];
const copy = [...numbers];
copy.push(3);
console.log(numbers); // [1, 2]
Spread создаёт новое значение верхнего уровня, а не меняет исходное.
Быстрая памятка
- spread использует
...для раскрытия значений - при вызове функции spread превращает массив в набор аргументов
- в массивах spread помогает копировать и объединять элементы
- в объектах spread помогает копировать и объединять свойства
- spread делает только поверхностную копию
- spread и rest используют одинаковый синтаксис, но делают противоположные вещи
Коротко
Spread в JavaScript позволяет раскрывать массивы, строки, итерируемые значения и свойства объектов через .... Главное, что стоит запомнить: он очень удобен для вызова функций, копирования и объединения данных, но не делает глубокую копию и не должен путаться с rest-параметрами.