Во время работы над 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.