Оператор распространения в JavaScript

В ES6 был введен оператор распространения. Если вы видели в своем коде три точки, за которыми следует итерация (… arr), это именно то, о чем мы говорим.

Оператор распространения расширяет итерацию на месте и обеспечивает более короткий синтаксис для набора операций. Но что это вообще значит?

Давайте рассмотрим пару простых примеров, чтобы лучше понять это:

Пример 1:

Объединение массивов. Допустим, у нас есть два массива:

let arrayFirst = [1, 2, 3];
let arraySecond = [4, 5, 6];

Теперь, если мы хотим объединить массивы, мы должны написать что-то вроде:

let newArray = arrayFirst.concat(arraySecond);
console.log(newArray);
> [1, 2, 3, 4, 5, 6]

Попробуем сделать это с помощью оператора распространения:

let newArrayUsingSpreadOperator = [...arrayFirst, ...arraySecond];
console.log(newArrayUsingSpreadOperator);
> [1, 2, 3, 4, 5, 6]

Во втором сценарии, где мы используем оператор распространения, механизм JS расширяет arrayFirst и arraySecond на месте, а newArrayUsingSpreadOperator назначается с массивом [1, 2, 3, 4, 5, 6].

Мы даже можем сделать что-то вроде:

let insertIntoArray = [0, ...arrayFirst, ...arraySecond, 7, 8, 9];
console.log(insertIntoArray);
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Пример 2:

Клонирование массивов. Предположим, мы хотим сделать копию существующего массива, чтобы изменить его:

let array = [1, 2, 3];
let arrayCopy = array;

Теперь, если мы хотим добавить новые элементы только в arrayCopy, исходный массив также будет изменен, поскольку оператор = не создает новую ссылку для клонированного массива.

arrayCopy.push(4);
console.log(array);
> [1, 2, 3, 4]
console.log(arrayCopy);
> [1, 2, 3, 4]

Выше мы видим, что исходный массив также изменяется. Этого можно избежать, клонируя исходный массив с помощью оператора распространения. Вы заметите, что изменение скопированного массива не изменяет исходный массив, поскольку создает новую ссылку для массива:

let arrayCopy = [...array];
arrayCopy.push(4);
console.log(array);
> [1, 2, 3]
console.log(arrayCopy);
> [1, 2, 3, 4]

Единственная проблема здесь заключается в том, что клонирование с новым эталоном работает только для первого уровня. Поэтому, если у вас есть вложенные массивы, использование оператора распространения не решит проблему со ссылками.

Пример 3:

Вызов функций. Предположим, у нас есть функция, которая принимает три числа и возвращает их сумму. мы можем использовать оператор распространения следующим образом:

const funcSum = function(num1, num2, num3){
 let sum = num1 + num2 + num3;
 return sum;
}
console.log(funcSum(...arrayFirst));
> 6

Результатом этой функции будет 6. Опять же, здесь происходит то, что оператор распространения расширяет массив на месте. Таким образом, вызов функции выглядит примерно как funcSum (1, 2, 3). Это выглядит намного лучше и чище, чем использование чего-то вроде:

funcSum(arrayFirst[0], arrayFirst[1], arrayFirst[2]);

Пример 4:

Объектные литералы. Оператор распространения также можно использовать с объектами. Однако работает это немного иначе. Давайте посмотрим на пример, в котором оператор распространения используется для создания копии объекта с дополнительными свойствами:

let a = {'firstName': 'John', 'lastName': 'Doe'}
let b = {'city': 'XYZ', 'zip': '12345'}
let c = {...a, ...b}
console.log( c );
> {city: "XYZ", firstName: "John", lastName: "Doe", zip: "12345" }

Оператор распространения может использоваться для создания объектов с новыми или обновленными свойствами. Например:

let a = {'firstName': 'John', 'lastName': 'Doe'}
let b = {'city': 'XYZ', 'zip': '12345'}
let c = {'city': 'ABC'}
let d = {...a, ...b, ...c}
console.log( d );
> {city: "ABC", firstName: "John", lastName: "Doe", zip: "12345" }

Оператор распространения определенно полезен при работе с массивами и объектами в JavaScript и может сэкономить время разработчиков при кодировании!