[Перевод] JavaScript ES6: оператор расширения
JavaScript постоянно развивается, в нём появляются различные новшества и улучшения. Одно из таких новшеств, появившееся в ES6 — оператор расширения. Он выглядит как троеточие (...
). Этот оператор позволяет разделять итерируемые объекты там, где ожидается либо полное отсутствие, либо наличие одного или нескольких аргументов. Сухие определения обычно бывает непросто понять без практических примеров. Поэтому рассмотрим несколько вариантов использования оператора расширения, которые помогут вникнуть в его сущность.
Пример №1: вставка массивов в другие массивы
Взгляните на этот код. Тут оператор расширения не используется:
var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];
console.log(arr);
Выше мы создали массив mid
. Затем создан второй массив, arr
, который содержит массив mid
. В конце программы массив arr
выводится в консоль. Как вы думаете, каким станет этот массив после добавления в него массива mid
? Взглянем на то, что выведет программа:
[1, 2, [3, 4], 5, 6]
Вы думали, что так и будет?
Вставляя массив mid
в массив arr
, мы получили в итоге один массив, вложенный в другой. Если это именно то, что было нужно, то придираться тут не к чему. Однако, что если целью написания вышеприведённого кода было получение массива чисел от 1 до 6? Для того чтобы достичь этой цели, можно использовать оператор расширения. Вспомните о том, что этот оператор позволяет разделять массивы на отдельные элементы.
Рассмотрим следующий пример. Всё тут, за исключением одного места, точно такое же, как и в предыдущем фрагменте кода. Разница заключается в том, что теперь для того, чтобы вставить содержимое массива mid
в массив arr
, применяется оператор расширения:
var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];
console.log(arr);
Если этот код выполнить, то в результате будет выведено следующее:
[1, 2, 3, 4, 5, 6]
Вспомните описание оператора расширения, приведённое в самом начале материала. Только что вы увидели его в действии. Как можно заметить, когда мы создаём массив arr
и используем оператор расширения, применяя его к массиву mid
, то, вместо вставки в один массив другого массива, как объекта, этот другой массив «разбивается на части». Разделение вставляемого массива в нашем случае означает, что все элементы этого массива, поодиночке, будут добавлены в массив arr
. В результате, вместо конструкции из вложенных массивов, получился один массив, содержащий числа от 1 до 6.
Пример №2: математические вычисления
В JavaScript есть встроенный объект Math
, который позволяет выполнять математические вычисления. В данном примере нас интересует метод Math.max()
. Если вы с этим методом не знакомы, сообщаем, что он возвращает самое большое из переданных ему чисел, причём допустимо использовать его как без аргументов, так и с одним или несколькими аргументами. Вот несколько примеров:
Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100
Как видите, если требуется найти максимальное значение нескольких чисел, Math.max()
нужно несколько параметров. К сожалению, если надо найти максимальный элемент числового массива, сам массив методу Math.max()
передать нельзя. До появления в JS оператора расширения самым простым способом поиска максимального элемента в массиве с помощью Math.max()
было использование метода apply()
:
var arr = [2, 4, 8, 6, 0];
function max(arr) {
return Math.max.apply(null, arr);
}
console.log(max(arr));
Выше представлена работающая конструкция, но выглядит всё это не очень-то приятно.
А вот как то же самое делается с помощью оператора расширения:
var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);
console.log(max);
Вместо того, чтобы создавать функцию и использовать метод apply()
для возвращения результата работы метода Math.max()
, тут нужно лишь две строки кода. Оператор расширения «вытаскивает» из массива все его элементы и они поступают на вход метода Math.max()
.
Пример №3: копирование массивов
В JS нельзя скопировать массив, просто приравняв новую переменную той, которая уже содержит существующий массив. Рассмотрим пример:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
console.log(arr2);
Если его выполнить, можно увидеть следующее:
['a', 'b', 'c']
На первый взгляд всё работает как надо, может показаться, что мы скопировали значения массива из переменной arr
в переменную arr2
. Однако на самом деле произошло совсем другое. В JavaScript, в операциях присваивания объектов переменным (а массивы — это тоже объекты), оперируют ссылками на них, а не их значениями. Это означает, что в arr2
была записана та же ссылка, которая хранилась в arr
. Другими словами, всё, что мы сделаем после этого с arr2
, повлияет и на arr
(и наоборот). Взгляните на это:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
arr2.push('d');
console.log(arr);
Тут мы поместили новый элемент, строку d
, в конец массива arr2
. Однако, выведя в консоль arr
, можно увидеть, что массив, на который ссылается эта переменная, также изменился:
['a', 'b', 'c', 'd']
Надо заметить, что ничего страшного тут не происходит. Перед нами — стандартное поведение JS. А для того, чтобы действительно создать копию массива, можно воспользоваться оператором расширения. Вот пример использования этого оператора для копирования массивов. Код выглядит практически так же, как и в вышеприведённом примере. Однако здесь используется оператор расширения, применённый к исходному массиву, а вся эта конструкция помещена в квадратные скобки:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
console.log(arr2);
Выполнив этот код, можно увидеть, что выводит он то, чего мы от него и ожидаем:
['a', 'b', 'c']
В этом примере массив arr
«разворачивается», в нашем распоряжении оказываются его отдельные элементы, которые попадают в новый массив, ссылка на который записывается в arr2
. Теперь можно делать с arr2
что угодно и это не повлияет на arr
:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
arr2.push['d'];
console.log(arr);
Опять же, причина, по которой это всё работает, заключается в том, что оператор расширения «вытаскивает» значения элементов массива arr
и они попадают в новый массив arr2
. Таким образом, мы записываем в arr2
ссылку на новый массив, содержащий элементы из массива arr
, а не ссылку на тот массив, на который ссылается переменная arr
. Это и отличает данный пример от предыдущего.
Дополнительный пример: преобразование строки в массив
Напоследок — вот один интересный пример использования оператора расширения для преобразования строк в массивы. Здесь достаточно применить этот оператор к нужной строке, поместив всю эту конструкцию в пару квадратных скобок:
var str = "hello";
var chars = [...str];
console.log(chars);
Итоги
Сегодня мы рассмотрели особенности работы с оператором расширения. Это — одна из новых возможностей JavaScript ES6, полезная мелочь, которая вполне способна улучшить читаемость кода и немного сократить его размер.
Уважаемые читатели! Пользуетесь ли вы оператором расширения в JavaScript?