Когда-то давно произошла значительная модернизация языка Javascript под названием ES6 / ES2015. Он представил много разных новых функций. Одним из них были три последовательные точки, которые мы можем написать перед любым совместимым контейнером (объектами, массивами, строками, наборами, картами). Эти крошечные точки позволяют нам писать более элегантный и лаконичный код. Я объясню, как работают три точки, и покажу наиболее распространенные варианты использования.

Три последовательные точки имеют два значения: оператор распространения и оператор отдыха.

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

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

const newArray = [‘first’, …anotherArray];

Остальные параметры

Синтаксис остальных параметров позволяет нам представить неопределенное количество аргументов в виде массива. Именованные параметры могут быть перед остальными параметрами.

const func = (first, ...rest) => {};

Случаи применения

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

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

Когда нам нужно изменить массив, но мы не хотим касаться исходного (его могут использовать другие), мы должны его скопировать.

const fruits = ['apple', 'orange', 'banana'];
const fruitsCopied = [...fruits]; // ['apple', 'orange', 'banana']
console.log(fruits === fruitsCopied); // false
// old way
fruits.map(fruit => fruit);

Он выбирает каждый элемент внутри массива и помещает каждый из этих элементов в новую структуру массива. Мы можем скопировать массив с помощью оператора `map` и сделать отображение идентичности.

Уникальный массив

Мы хотим отсортировать повторяющиеся элементы из массива. Какое самое простое решение?

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

const fruits = ['apple', 'orange', 'banana', 'banana'];
const uniqueFruits = [...new Set(fruits)]; // ['apple', 'orange', 'banana']
// old way
fruits.filter((fruit, index, arr) => arr.indexOf(fruit) === index);

Объединить массивы

Мы можем объединить два отдельных массива с помощью метода concat, но почему бы не использовать снова оператор распространения?

const fruits = ['apple', 'orange', 'banana'];
const vegetables = ['carrot'];
const fruitsAndVegetables = [...fruits, ...vegetables]; // ['apple', 'orange', 'banana', 'carrot']
const fruitsAndVegetables = ['carrot', ...fruits]; // ['carrot', 'apple', 'orange', 'banana']
// old way
const fruitsAndVegetables = fruits.concat(vegetables);
const fruitsAndVegetables = fruits.push('carrot');

Передавать аргументы как массивы

Передача аргументов - это то место, где оператор распространения начинает делать наш код более читабельным. До ES6 нам приходилось применять функцию к arguments. Теперь мы можем просто распространить параметры на функцию, что приведет к гораздо более чистому коду.

const mixer = (x, y, z) => console.log(x, y, z);
const fruits = ['apple', 'orange', 'banana'];
mixer(...fruits); // 'apple', 'orange', 'banana'
// old way
mixer.apply(null, fruits);

Нарезка массива

Нарезка проще с методом slice, но при желании можно использовать оператор распространения и для этого варианта использования. Мы должны назвать оставшиеся элементы один за другим, так что это не лучший способ вырезать из середины большого массива.

const fruits = ['apple', 'orange', 'banana'];
const [apple, ...remainingFruits] = fruits; // ['orange', 'banana']
// old way 
const remainingFruits = fruits.slice(1);

Преобразование аргументов в массив

Аргументы в Javascript - это объекты, подобные массивам. Вы можете получить к нему доступ с помощью индексов, но не можете вызывать для него методы массива, такие как map, filter. Аргументы - это итерируемые объекты, так что мы можем с ними делать? Выкладываю на массив!

const mixer = () => console.log([...arguments]);
mixer('apple'); // ['apple']
// old way
Array.prototype.map.call(arguments, arg => arg);

Повторное преобразование аргументов в массив

Преобразование аргументов в массив можно упростить еще больше, если мы будем использовать остальные аргументы в определении функции.

const mixer = (...arguments) => console.log(arguments);
mixer('apple'); // ['apple']

Преобразование NodeList в массив

Аргументы подобны NodeList, возвращаемому функцией querySelectorAll. Они также немного похожи на массивы, но не имеют соответствующих методов.

[...document.querySelectorAll('div')];
// old way
Array.prototype.slice.call(document.querySelectorAll('div'));

Копирование объекта

Наконец, мы подошли к манипуляциям с объектами. Копирование работает так же, как и с массивами. Раньше это можно было сделать с Object.assign и пустым литералом объекта.

const todo = { name: 'Clean the dishes' };
const todoCopied = { ...todo }; // { name: 'Clean the dishes' }
console.log(todo === todoCopied); // false
// old way
Object.assign({}, todo);

Объединить объекты

Единственная разница в слиянии заключается в том, что свойства с одним и тем же ключом перезаписываются. Самое правое свойство имеет наивысший приоритет.

const todo = { name: 'Clean the dishes' };
const state = { completed: false };
const nextTodo = { name: 'Ironing' };
const merged = { ...todo, ...state, ...nextTodo }; // { name: 'Ironing', completed: false }
// old way
Object.assign({}, todo, state, nextTodo);

Разбиение строки на символы

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

const country = 'USA';
console.log([...country]); // ['U', 'S', 'A']
// old way
country.split('');

Вот и все

Мы рассмотрели множество различных вариантов использования трех точек в Javascript. Как видите, ES6 не только повысил эффективность написания кода, но и представил несколько интересных способов решения давно существующих проблем. Теперь все основные браузеры поддерживают новый синтаксис; все приведенные выше примеры можно попробовать в консоли браузера, читая эту статью. В любом случае вы начинаете использовать оператор спреда и остальные параметры. Это отличное дополнение к языку и отличное решение для изучения.