W3docs

Rest-параметры и spread-синтаксис в JavaScript

Rest-параметры собирают аргументы в array, spread-синтаксис разворачивает итерируемые объекты. Узнайте, как использовать оба в JavaScript ES6.

В JavaScript токен из трёх точек ... выполняет две противоположные функции в зависимости от места его написания. Как параметр функции он собирает множество аргументов в один array — это rest-параметр. Везде в остальных местах он разворачивает итерируемый объект или object в отдельные элементы — это spread-синтаксис. Один и тот же символ, зеркальное значение.

Оба были введены в ES6 (2015). На этой странице рассматриваются rest-параметры (включая правило о том, что они должны стоять последними), spread в вызовах функций, в литералах array и object, способы копирования и слияния с помощью spread, различия между rest и spread, а также преимущества обоих перед старым объектом arguments.

Понимание rest-параметров в JavaScript

Rest-параметр позволяет функции принимать неограниченное количество аргументов и получать их в виде настоящего array. Вы пишете ... с именем; это имя становится array, содержащим каждый аргумент, который не был сопоставлен с предыдущим параметром.

Синтаксис и использование

В примере ниже numbers — обычный array, поэтому вы можете вызывать методы array, такие как reduce, прямо на нём — никакого преобразования не нужно.

javascript— editable

Rest-параметр должен быть последним

Функция может иметь только один rest-параметр, и он должен быть последним в списке параметров. Именованные параметры перед ним заполняются первыми; rest-параметр затем захватывает всё оставшееся. Размещение его в любом другом месте вызовет SyntaxError.

javascript— editable

Преимущества перед объектом arguments

До ES6 единственным способом прочитать все аргументы был специальный объект arguments, доступный внутри не-стрелочных функций. Rest-параметры лучше практически во всём:

  • Настоящий array. arguments похож на array (у него есть length и индексы), но ему не хватает map, filter, reduce и т.д. Rest-параметр — это настоящий array.
  • Явный и читаемый. Сигнатура function sum(...numbers) говорит читателю, что функция принимает переменный список. arguments невидим в сигнатуре.
  • Можно именовать только дополнительные аргументы. Совмещайте фиксированные параметры с rest-параметром, как показано выше — arguments всегда содержит каждый аргумент, включая те, что уже именованы.
  • Работает со стрелочными функциями. У стрелочных функций нет собственного объекта arguments, поэтому rest-параметр — единственный способ собрать переменные аргументы в стрелочной функции.
javascript— editable

Погружение в spread-синтаксис

Spread-синтаксис разворачивает итерируемый объект — array, string, Set, Map или любой итерируемый объект — в отдельные элементы везде, где ожидается список значений. Существуют три контекста, где он используется: вызовы функций, литералы array и литералы object.

Spread в литералах array

Внутри [ ] spread вставляет каждый элемент итерируемого объекта в новый array. Это самый чистый способ вставить один array в другой на любой позиции:

javascript— editable

Поскольку строки итерируемы, их развёртка даёт array символов:

javascript— editable

Spread в вызовах функций

В вызове функции spread превращает array обратно в список отдельных аргументов. Это заменяет старый паттерн func.apply(null, array):

javascript— editable

Spread в литералах object

Внутри { } spread копирует собственные перечисляемые свойства object в новый object. При совпадении ключей побеждает более позднее значение — что делает spread идеальным для применения переопределений или значений по умолчанию:

javascript— editable

Копирование и слияние

Spread — идиоматический способ создать поверхностную копию или объединить коллекции без изменения оригиналов:

javascript— editable

Spread поверхностный. Он копирует только значения верхнего уровня. Вложенные object и array по-прежнему разделяются по ссылке, поэтому изменение вложенного значения влияет на обе копии:

javascript— editable

Rest против Spread: как их различить

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

Rest-параметрSpread-синтаксис
Где встречаетсяВ списке параметров функцииВ вызове, литерале array или object
Что делаетСобирает множество значений в один arrayРазворачивает один итерируемый объект/object во множество значений
Сторона от =Левая сторона (цель деструктуризации)Правая сторона (производимое значение)
Примерfunction f(...args) {}f(...args)

Простой тест: если ...x получает значения — это rest; если производит значения — это spread.

Совместное использование rest-параметров и spread-синтаксиса

Эти два инструмента — зеркальные образы, поэтому они естественно сочетаются: rest собирает аргументы в array на входе, а spread разворачивает array в аргументы на выходе:

javascript— editable

Распространённый реальный паттерн — обёртка, которая перенаправляет все аргументы другой функции:

javascript— editable

Деструктуризация с паттерном rest

В деструктурирующем присваивании паттерн rest захватывает свойства или элементы, которые не были явно именованы. В object он создаёт object из оставшихся ключей; в array — array из оставшихся элементов.

javascript— editable

Заключение

Токен ... — одно из самых полезных дополнений, которые ES6 внёс в JavaScript. Как rest-параметр он собирает переменное количество аргументов в чистый array (и заменяет неудобный объект arguments); как spread-синтаксис он разворачивает итерируемые объекты в вызовы функций, литералы array и object, предоставляя лаконичные поверхностные копии и слияния. Помните два правила, которые чаще всего вводят в заблуждение: rest-параметр должен быть последним параметром, а копии через spread поверхностные.

Связанные темы

Практика

Практика
Что верно в отношении использования rest-параметров и spread-синтаксиса в JavaScript?
Что верно в отношении использования rest-параметров и spread-синтаксиса в JavaScript?
Was this page helpful?