Во время работы над JS101 Launch School эти три точки, ...
, продолжали появляться в решениях кода для небольших упражнений. Исходя из опыта работы с Java и Python, я не видел этого раньше, и сначала его использование было непонятным. Особенно сбивает с толку тот факт, что ...
, похоже, работает по-разному, в зависимости от контекста. Но после того, как я отважился изучить названия двух его применений (распространение и отдых) и то, что он делает в различных контекстах (поясняется ниже!), Теперь я считаю, что точки могут быть полезны в моей практике программирования.
Поскольку нетрудно найти объяснения синтаксиса распространения и отдыха в другом месте, это сообщение в блоге стремится отличаться, максимально упрощая понимание того, что делает синтаксис. Таким образом, он предназначен для новичков в идеях выкладывания и отдыха.
Мы рассмотрим пары примеров, единственное отличие которых состоит в использовании трех точек, чтобы понять, как это меняет поведение кода. Сообщение сгруппировано по вариантам использования. И мы в основном сосредоточимся на использовании этого синтаксиса по отношению к массивам, хотя он также может использоваться со строками и объектами.
В чем разница между Rest и Spread?
Синтаксис ...
используется в JavaScript двумя способами: как шаблон отдыха и как оператор распространения. В качестве оператора распространения ...
позволяет развернуть элементы из массива, в то время как в качестве шаблона покоя использование точек помещает в массив иначе разгруппированные элементы.
Было бы полезно понять, что, хотя шаблоны покоя и распределения демонстрируют противоположное поведение, они похожи в том, что они перемещают элементы в массивы и из них.
Синтаксис распространения для копирования и объединения массивов
Поскольку синтаксис ...
используется для двух целей, единственный способ узнать, чего ожидать от его поведения, - это посмотреть на его контекст. Начнем с примеров синтаксиса распространения:
let arr = ['a', 'b']; let nestedArr = [arr]; let spreadCopy = [...arr]; nestedArr; // [ [ 'a', 'b' ] ] spreadCopy; // [ 'a', 'b' ]
Когда ...
используется в литерале массива, каждый элемент массива, следующий за ...
, расширяется в новый массив. В spreadCopy
оператор распространения используется для создания копии arr
. Напротив, в nestedArr
исходный массив из arr
вложен в другой массив. Было бы полезно думать об элементах из arr
как о «выходящих» из своих скобок в spreadCopy
. Это хороший и лаконичный способ создания копии массива. Другой пример:
let arr1 = [1,2,3]; let arr2 = [4,5,6]; let doubleNested = [arr1, arr2]; let spreadArr = [...arr1, ...arr2]; doubleNested; // [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] spreadArr; // [ 1, 2, 3, 4, 5, 6 ]
В приведенном выше примере показано, как объединять массивы с помощью ...
. Разница между выводом doubleNested
и spreadArr
отражает поведение первого примера. Здесь ...
эффективно удаляет вложенные массивы и расширяет их элементы во внешний массив. Еще раз, было бы полезно подумать о том, как элементы arr1
и arr2
выходят из своих скобок и все их элементы вставляются в новый массив. Результат такой же, как при вызове arr1.concat(arr2)
.
Синтаксис распространения для разделения строки литералом массива
Ту же идею можно применить и для строк:
let string = 'hello'; let stringToArr = [string]; let spreadString = [...string]; stringToArr; // [ 'hello' ] spreadString; // [ 'h', 'e', 'l', 'l', 'o' ]
В этом примере использование ...
аналогично вызову split('')
на string
. Но идея аналогична приведенным выше примерам массивов: каждый символ в строке расширяется в новый массив. Еще раз, разница становится очевидной при сравнении вывода stringToArr
с выводом spreadString
.
Синтаксис расширения для передачи нескольких аргументов в вызовах функций
При использовании в качестве аргумента при вызове функции ...
будет расширять переданный массив в определенные аргументы функции. Вот пример с синтаксисом распространения и без него:
function spread(a, b, c) { return a + b + c; } let numbers = [1, 2, 3]; spread(...numbers); // 6 spread(numbers); // '1,2,3undefinedundefined'
Когда вызывается spread(...numbers)
, оператор распространения распаковывает три элемента numbers
в аргументы a
, b
и c
. Затем они складываются внутри функции, и возвращается сумма.
Напротив, при вызове без синтаксиса распространения spread(numbers)
сохраняет массив, переданный numbers
, и присваивает его переменной a
. Затем он интерпретирует знаки +
в объявлении функции как операторы конкатенации строк, неявно преобразует numbers
в строку и объединяет результат с неопределенными переменными b
и c
, в результате чего получается странно выглядящий результат выше.
Синтаксис отдыха для обработки нескольких параметров в определениях функций
Теперь перейдем к синтаксису отдыха. В определении функции ...
поместит любое количество переданных аргументов в один массив. Обратите внимание, что это поведение противоположно тому, как мы можем использовать оператор распространения в вызове функции. Важно помнить, что синтаксис rest должен быть последним параметром, определенным в функции. Вот пример:
function rest(...args) { console.log(args) } function withoutRest(args) { console.log(args) } rest(1, 2, 3, 4); // [ 1, 2, 3, 4 ] withoutRest(1, 2, 3, 4); // 1
Здесь мы видим, что вызов rest
с аргументами 1, 2, 3, 4
выводит массив, который объединяет все переданные аргументы. Когда мы передаем те же аргументы в withoutRest
, мы получаем на выходе 1
. Это связано с тем, что параметр args
в этом определении функции принимает только один аргумент и поэтому игнорирует последующие аргументы.
Синтаксис Rest для присвоения нескольких элементов переменной массива
Синтаксис rest также может использоваться в назначении деструктуризации массива. Вот пример:
let arr = [1, 2, 3]; let [a, ...b] = arr; let [c, d] = arr; a; // 1 b; // [ 2, 3 ] c; // 1 d; // 2
Как и в определении функции, использование здесь элемента rest поместит несколько элементов в массив. Таким образом, b
назначается остальной части arr
, которая не захватывается a
. Для сравнения, d
опускает точки и поэтому назначается только второму элементу arr
. Подробнее о назначении деструктуризации массива см. Документация MDN.
Последняя мысль
Это должно было быть кратким и ясным изложением основ синтаксиса распространения и отдыха с упором на понимание того, что на самом деле три точки делают в коде. Подводя итог, можно сказать, что синтаксис - это простой способ копирования и объединения массивов, а также разделения символов в строке. Это также может быть полезным способом передачи нескольких элементов в вызовах функций и определениях, а также в назначениях деструктуризации массива. Как всегда, если вам нужно больше информации по теме, обратитесь к документации MDN.