Операторы rest и spread в JavaScript - Академия Selectel

Операторы rest и spread в JavaScript

В статье разберем, что означает каждый оператор и как использовать их на практике.

Изображение записи

Оператор rest группирует несколько значений в JavaScript, а spread разгруппировывает — вместе они позволяют писать код проще, понятнее и красивее.

Что такое оператор rest в JavaScript

Сперва рассмотрим простой пример. У нас есть функция, которая складывает числа:


      function sum(a, b) {
 return a + b;
}

console.log(sum(5, 2)); // 7

Она отлично справляется с задачей: на вход принимает два числа и на выходе отдает сумму. Но предположим, что мы хотим сделать так, чтобы функция принимала неограниченное количество чисел. Как это реализовать?
Скорее всего, вы подумаете о массиве:


      function sum(numbers) {
 let result = 0;

 for (let i = 0; i < numbers.length; i++) {
   result += numbers[i];
 }

 return result;
}

console.log(sum([3, 5, 4, 1, 2])); // 15

Rest — это синтаксис в JavaScript, который позволяет собирать неограниченное количество аргументов функции и свойств объекта в массив (или объект). Если сказать проще, то rest берет все, что осталось, и объединяет. Используют оператор с помощью трех точек «…».

В примере выше …numbers превращает все переданные аргументы в массив, то есть в параметр собираются все оставшиеся аргументы.

  • Если вызвать sum(1, 2, 3), то внутри функции numbers будет [1, 2, 3].
  • Если вызвать sum(10, 20), то numbers будет [10, 20].
  • Если вызвать без аргументов — [].

А если у функции должны быть и другие параметры, помимо тех, что собираются в массив? Все просто, сначала прописываем параметры, которые не войдут в объединенный массив, а остальные «соберет» rest:


      function welcome(prefix, ...names) {
 for (let name of names) {
   console.log(`${prefix}, ${name}!`);
 }
}

welcome("Привет", "Андрей", "Оля", "Саша");

 return result;
}

Вывод в консоли: Привет: Андрей! Привет, Оля! Привет, Саша!
Результат в консоли.

Здесь первый prefix становится отдельным параметром, а все остальные аргументы попадают в массив …names.

​​Rest с массивами

Rest можно применять не только в функциях, но и в работе с массивами:


      const numbers = [1, 2, 3, 4, 5];

const [first, second, ...rest] = numbers;

console.log(first);
console.log(second);
console.log(rest);
Вывод в консоли: 1, 2, [3, 4, 5].
Пример в консоли.

Здесь rest собрал все остатки массива после первых двух элементов. Кстати, в этом примере также используется деструктуризация — о ней я рассказал в предыдущей статье.

Rest в объектах

С массивами разобрались. Теперь узнаем, можно ли применять rest с объектами. Смотрим пример:


      const user = {
 name: "Андрей",
 age: 21,
 city: "Волгоград",
 profession: "разработчик"
};


const { name, ...other } = user;


console.log(name);
console.log(other);

Вывод в консоли: объект. {age: 21, city: ‘Волгоград’, profession: ‘разработчик’ }.
Пример в консоли.

Здесь добавили name в отдельную константу, а все остальное — в объект other. В некоторых случаях этот прием тоже будет полезным.

Что такое оператор spread в JavaScript

Вы уже знаете, что rest собирает элементы вместе, но есть и обратная операция — «разбор» элементов с помощью spread. Смотрим пример:


      const numbers1 = [1, 2, 3];
const numbers2 = [4, 5];
const combined = [...numbers1, ...numbers2];


console.log(combined);
Вывод в консоли объекта: [1, 2, 3, 4, 5]
Пример в консоли.

Все те же три точки, но в другом контексте. Оператор объединяет два массива с помощью одной строки. Конечно, это можно сделать с помощью встроенного метода — об этом расскажу в следующих статьях — или цикла, но посмотрите, как просто и лаконично выглядит код уже сейчас.

Spread — это синтаксис в JavaScript, который позволяет разобрать массив или объект на отдельные элементы. Его также используют с помощью трех точек «…» — он как rest, только работает наоборот. 

Если сказать проще, то spread убирает квадратные [] или фигурные {} скобки. Функция позволяет выполнять нужные манипуляции со вложенными элементами. Рассмотрим, как еще можно использовать spread.

Копирование массива

Как просто скопировать элементы массива в другой массив:


      const original = [1, 2, 3];
const copy = [...original];

console.log(copy);
console.log(original === copy);

В консоли. Видим false.
Результат в консоли.

Копирование — это уже отдельная тема для статьи. В этой операции многое зависит от того, что именно вы копируете и чего хотите достичь. Не будем останавливаться на этом. Ниже расскажу о том, что такое мутабельность и ссылки.

Работа с объектами


      const user = { name: "Андрей", age: 25 };
const info = { city: "Волгоград", profession: "разработчик"}
const combined = { ...user, ...info };


console.log(combined);

Вывод в консоли. Объект {name: ‘Андрей’, age: 21, city: ‘Волгоград’, profession: ‘разработчик’ }.
Результат в консоли. 

Вышло красиво и просто, согласитесь?

Передача аргументов в функцию

Помните функцию sum из примера в начале статьи. Как быть, если мы захотим передать в нее массив? Сможет ли функция использовать rest и принимать неограниченное количество параметров? На помощь приходит spread:


      function sum(...numbers) {
 let result = 0;

 for (let i = 0; i < numbers.length; i++) {
   result += numbers[i];
 }

 return result;
}

const numbers = [1, 3, 5, 7]
console.log(sum(...numbers)); // 16

Вот так, все просто. Оператор разбирает массив из набора и затем опять собирает. Конечно, пример абсолютно надуманный, но поверьте, в практике такая реализация имеет место быть.

Заключение

Операторы rest и spread в JavaScript — это два приема с одинаковым синтаксисом «…», но противоположным действием. Rest собирает оставшиеся значения в массив или объект — удобно для функций, массивов и объектов. Spread, наоборот, раскрывает коллекцию на отдельные элементы — подходит для объединения, копирования и передачи аргументов. Вместе они делают код более компактным и читаемым.