Что означают три точки (...) в JavaScript

  • 14 февраля, 09:54
  • 19317
  • 1

Оператор spread для массива/объекта

Предположим, что у вас есть следующий объект:

const adrian = {
fullName: 'Adrian Oprea',
occupation: 'Software developer',
age: 31,
website: 'https://oprea.rocks'
};

Например, вы хотите создать новый объект (человека) с другим именем и сайтом, но с той же профессией и возрастом.

Вы можете сделать это, указав только те свойства, которые вам нужны и использовать оператор spread для остальных свойств, как показано в примере:

const bill = {
...adrian,
fullName: 'Bill Gates',
website: 'https://microsoft.com'
};

Вышеуказанный код распространяет объект adrian и принимает все его свойства, перезаписывая потом имеющиеся темы, что мы передаем. Он копирует свойства объекта adrian только что созданного объекта, а затем явно перезаписывает fullName и webSite

В этом случае, поскольку мы указали свойства fullName и website после того, как оператор spread начал работать, двигатель JavaScript достаточно умен, чтобы знать, что мы хотим перезаписать начальные значения тех свойств, которые поступают из исходного объекта.

Похожая ситуация с массивами. За исключением того, что вместо ключей и значений, оператор распространяет индексы и значения. В отличие от распространения объекта, где вы не будете иметь дублированных свойств, поскольку именно так работают объекты JavaScript (у вас не может быть объекта с двумя свойствами fullName), в массивах можно иметь повторяющиеся значения, в том случае, если вы планируете реализовать что-то вроде этого примера объекта.

Нижеследующий код приведет к тому, что у вас будет массив с повторяющимися элементами:

const numbers1 = [1, 2, 3, 4, 5];
const numbers2 = [ ...numbers1, 1, 2, 6,7,8]; // this will be [1, 2, 3, 4, 5, 1, 2, 6, 7, 8]

Думайте об этом как о замене Array.prototype.concat()

Оператор Rest

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

Использован таким образом оператор rest позволяет разработчику создавать функции, которые могут принимать неограниченное количество аргументов, которые также называются функциями арности (размерности) переменных или вариативными функциями.

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

Наивная реализация, использования оператора rest:

function sum(...numbers) {
return numbers.reduce((accumulator, current) => {
return accumulator += current;
});
};

sum(1,2) // 3
sum(1,2,3,4,5) // 15

Самым простым объяснением было бы то, что оператор rest принимает аргументы, которые принимает функция и выгружает их в массив, который вы можете использовать позже.

Это можно сделать, попросив пользователя передать массив чисел. Технически это выполнимо, но является плохим UX для вашего API, поскольку пользователи ожидают вызов функции итоге с простыми числами, а не со списком чисел.

Также можно использовать массив arguments. Это тоже правда, но будьте осторожны, arguments не является действительным массивом, а только подобным массиву объектом (объект со свойством length). Для первого вызова нашей функции из прошлого примера это выглядит так:

{
'0': 1,
'1': 2,
'length': 2
}

Чтобы управлять этим объектом и использовать методы массивов, таких как reduce из прошлого примера, вам надо сделать Array.prototype.slice.call(arguments).

Вот прошла функция, написанная с использованием Array#slice:

function sum() {
const args = Array.prototype.slice.call(arguments);
return args.reduce((accumulator, current) => {
return accumulator += current;
});
}

sum(1,2) // 3
sum(1,2,3,4,5) // 15

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

Суть в том, что вышеуказанный код может запутать тех, кто будет его читать. Поэтому, не следует заходить дальше, чем как указано на Mozilla Developer Network.

За материалами www.oprea.rocks


1 комментарий
Сортировка:
Добавить комментарий
Ihor
Ihor 2022, 3 ноября, 19:25
0

Дякую за статтю!


IT Новости

Смотреть все