Операторы Spread и Rest в Javascript ES6 (просто и c примерами)
Spread оператор (оператор расширения) 'берет' каждый отдельный элемент итерируемого объекта (массив) и 'распаковывает' его в другой итерируемый объект (массив).
Что такое итерируемые (перебираемые) объекты?
К итерируемым объектам можно отнести все, что можно перебрать с помощью цикла for..of
.
Большая часть задач, где приходится использовать оператор spread, касается массивов и строк.
Где и когда используется spread?
Предположим у нас есть 2 массива с сериалами.
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];
В какой-то момент мы решаем создать еще один массив, который будет включать все сериалы из обоих массивов. Как это сделать?
Мы можем использовать метод .concat()
, который возвращает новый массив, состоящий из элементов 1-го и 2-го массива.
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = tvSeriesOne.concat(tvSeriesTwo);5console.log(tvSeries);6// [ "Ozark", "Fargo", "Dexter", "Mr. Robot", "Barry", "Suits" ]
Что если мы захотим вставить сериал Sherlock в середину нашего общего списка?
Теоретически, мы также сможем это сделать с помощью метода .concat()
:
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34let tvSeries = [];56tvSeries = tvSeries.concat(tvSeriesOne);7tvSeries.push('Sherlock');8tvSeries = tvSeries.concat(tvSeriesTwo);910console.log(tvSeries);11// [ "Ozark", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]
Если использовать оператор spread, то наш код будет выглядеть более коротко и понятно.
Так будет выглядеть создание одного общего массива с помощью оператора spread:
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = [...tvSeriesOne, ...tvSeriesTwo];5console.log(tvSeries);6// [ "Ozark", "Fargo", "Dexter", "Mr. Robot", "Barry", "Suits" ]
То есть мы использовали оператор spread, чтобы взять каждый сериал из 1-го и 2-го массива и добавили его в новый массив tvSeries
.
Также можно добавить Sherlock в середину общего списка:
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = [...tvSeriesOne, 'Sherlock', ...tvSeriesTwo];5console.log(tvSeries);6// [ "Ozark", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]
Теперь давайте попробуем создать копию нашего массива tvSeries
:
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = [...tvSeriesOne, 'Sherlock', ...tvSeriesTwo];5const allSeriesList = tvSeries;67console.log(allSeriesList);8// [ "Ozark", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]
Что если мы решим изменить первый элемент нового массива allSeriesList
с 'Ozark' на 'Friends'?
1allSeriesList[0] = 'Friends';
Нам удалось поменять 1-й элемент allSeriesList
на 'Friends'. Проблема в том, что мы также изменили наш исходный массив tvSeries
.
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = [...tvSeriesOne, 'Sherlock', ...tvSeriesTwo];5const allSeriesList = tvSeries;67allSeriesList[0] = 'Friends';89console.log(allSeriesList);10// [ "Friends", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]11console.log(tvSeries);12// [ "Friends", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]
На самом деле мы не создали копию массива. Переменная allSeriesList просто содержит ссылку на наш исходный массив (также как и tvSeries).
1-й способ создать копию массива – использовать метод .concat()
:
1let allSeriesList = [].conctat(tvSeries);
2-й способ - с помощью оператора spread. Можно создать новый пустой массив и добавить в него каждый элемент исходного массива.
1const tvSeriesOne = ['Ozark', 'Fargo', 'Dexter'];2const tvSeriesTwo = ['Mr. Robot', 'Barry', 'Suits'];34const tvSeries = [...tvSeriesOne, 'Sherlock', ...tvSeriesTwo];56// Создаем копию7const allSeriesList = [...tvSeries];8// Меняем первый элемент новго массива9allSeriesList[0] = 'Friends';1011console.log(tvSeries);12// [ "Ozark", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]13console.log(allSeriesList);14// [ "Friends", "Fargo", "Dexter", "Sherlock", "Mr. Robot", "Barry", "Suits" ]
Таким образом, мы использовали оператор spread, чтобы создать копию массива tvSeries
.
Наши изменения в новом массиве allSeriesList
никак не затронули исходный массив tvSeries
.
Оператор Rest
Визуально, оператор rest …
(три точки) похож на оператор spread, но выполняет
противоположную функцию.
Spread забирает каждый элемент из массива и распаковывает в новый массив. Оператор rest забирает каждый элемент из массива и создает из них новый массив.
Есть 2 типа задач, где оператор rest используется чаще всего – в функциях и в процессе деструктуризации.
Пример 1. Оператор rest в функциях
Предположим, мы продаем пиццу.
Стоимость нашей самой популярной пиццы “Маргарита” – 500
Руб.
У нас есть функция, которая принимает стоимость конкретной пиццы и количество заказанной пиццы от разных посетителей:
Пример: Стоимость = 500, посетитель A заказал 3 штуки, посетитель B – 10 штук, посетитель C – 6 штук, D – 20 штук.
Мы будем записывать стоимость пиццы в переменную price
, а количество пицц в переменную rest (можно назвать как угодно).
1function buyPizza(price, ...rest) {2 console.log(price); // 5003 console.log(rest);4 // Array(4) [ 3, 10, 6, 20 ]5}6buyPizza(500, 3, 10, 6, 20);
Таким образом, мы можем подсчитать стоимость заказа для каждого посетителя:
1function buyPizza(price, ...rest) {2 return rest.map((quantity) => {3 return price * quantity;4 });5}6buyPizza(500, 3, 10, 6, 20);7// Array(4) [ 1500, 5000, 3000, 10000 ]
Мы можем добавить еще одну переменную, которая, например, будет подсчитывать стоимость доставки:
1function buyPizza(price, dostavka, ...rest) {2 console.log(price); // 5003 console.log(dostavka); // 2004 return rest.map((quantity) => {5 return price * quantity;6 });7}8buyPizza(500, 200, 3, 10, 6, 20);9// Array(4) [ 1500, 5000, 3000, 10000 ]
Пример 2. Оператор rest и деструктуризация
Предположим, у нас есть массив, в котором содержится название пиццы, ее 'ID' в нашей системе заказов и количества заказанной пиццы для разных посетителей:
1const pizza = ['Pepperoni', 2222, 5, 6, 10, 30, 1];
Мы можем получить название пиццы, ее ID и количества и присвоить 3-м новым переменным, используя оператор rest в процессе деструктуризации.
1const pizza = ['Pepperoni', 2222, 5, 6, 10, 30, 1];23const [name, id, ...rest] = pizza;4console.log(name); // Pepperoni5console.log(id); // 22226console.log(rest);7// [ 5, 6, 10, 30, 1 ]
Таким образом мы собрали все количества заказанной пиццы и создали из них отдельный новый массив.