В этом уроке мы познакомимся с фичей, которую представляют нам динамические языки. Она называется rest operator или операция rest.
Разоблачение списков
Вспомним пример со списками. В курсе Последовательности мы использовали специальный конструктор l
, который принимает на вход любое количество параметров:
const numbers = l(1, 10, 23, 234)
export const l = (...elements) =>
// elements [1, 10, 23, 234]
elements.reverse().reduce((acc, item) => cons(item, acc), null)
Количество параметров динамическое. Мы можем не передать ни одного, и тогда у нас получится пустой список. А можем передать их сколько угодно, и тогда они превращаются в один список.
Если мы посмотрим определение этой функции, то увидим внутри новую синтаксическую конструкцию. Она выглядит как три точки, и после нее идет идентификатор. В данном случае это элемент. А три точки — это и есть rest operator.
Operator переводится как операция, а не оператор. Это разные вещи.
При использовании этой операции все элементы помещаются в один массив. В комментарии // elements [1, 10, 23, 234]
видно его содержимое для этого списка. И после этого мы работаем с ним как с обычным массивом. В нашем примере мы вызываем reverse()
, reduce()
и постепенно добавляем элементы в null
через cons
. В итоге получаем список.
В этом примере много элементов, которые были бы непонятны на тот момент, когда мы знакомились со списками. Поэтому в тот момент мы не рассказывали о том, как они устроены внутри. Это было бы довольно сложно понять. Но теперь мы знаем это и можем читать и писать такой код.
Общая форма
Операцию rest можно комбинировать и с позиционными аргументами:
const fn = (a, b, ...theArgs) => {
console.log(a)
console.log(b)
console.log(theArgs)
}
fn ('first')
// first
// undefined
// []
В данном случае видно, что мы можем передавать первый и второй, третий параметры и так далее. И в конце можем использовать rest operator.
Rest — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.
Эта функция принимает на вход параметры, которые соберутся в один массив. Если мы попытаемся вызвать эту функцию с одним параметром, то первый параметр будет first
. Второй — undefined
, потому что он не был передан.
В случае с rest ситуация другая. theArgs
будет не undefined
, а пустой массив. И это правильно, так как нам не придется делать внутри проверки на undefined
. То есть если мы ничего не передали, массив будет пустой, что обычно является желаемым поведением. И дальше уже можно строить работу на основе этого подхода.
Массив
В стандартной библиотеке JavaScript операция rest периодически встречается. Один из самых популярных примеров — добавление элементов в массив. Функция push
у массива работает так:
const arr = []
arr.push()
arr.push(1)
arr.push(100, 23, 5)
arr.push(3, 100)
console.log(arr)
// [ 1, 100, 23, 5, 3, 100 ]
Здесь мы вызываем push
без аргументов, и ничего не происходит. Также можем передать один, два и более аргументов. В итоге массив наполнится и будет выглядеть так:
console.log(arr)
// [ 1, 100, 23, 5, 3, 100 ]
Выводы
В этом уроке мы познакомились с фичей, которая представляет нам динамические языки. Она называется rest operator или операция rest. Operator переводится как операция. При ее использовании все элементы помещаются в один массив rest — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.