Learn JavaScript

rest-параметры - сбор оставшихся аргументов функции в JavaScript

Rest-параметры позволяют собрать оставшиеся аргументы функции в один параметр.

Для этого используют ... перед именем параметра.

function sum(...numbers) {
  console.log(numbers);
}

sum(1, 2, 3); // [1, 2, 3]

Это удобно, когда заранее неизвестно, сколько аргументов передадут в функцию.

Синтаксис

Базовая запись выглядит так:

function name(...rest) {
  // код функции
}

Чаще всего rest-параметр называют args, numbers, items, values и так далее.

function logAll(...args) {
  console.log(args);
}

Что делают rest-параметры

Они собирают все оставшиеся аргументы в массив.

function showArguments(...args) {
  console.log(args);
}

showArguments("a", "b", "c"); // ["a", "b", "c"]

Важно: rest-параметр всегда даёт именно массив.

function test(...args) {
  console.log(Array.isArray(args)); // true
}

test(1, 2, 3);

Благодаря этому с ним сразу можно использовать методы массива: map(), filter(), reduce() и другие.

Когда аргументов нет

Если оставшихся аргументов нет, rest-параметр всё равно будет массивом, просто пустым.

function test(...args) {
  console.log(args);
}

test(); // []

Это удобно: не нужно отдельно проверять, существует ли параметр.

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

Часто сначала идут обязательные параметры, а потом rest.

function greet(mainUser, ...otherUsers) {
  console.log(mainUser);
  console.log(otherUsers);
}

greet("Анна", "Игорь", "Олег");
// "Анна"
// ["Игорь", "Олег"]

Здесь:

  • mainUser получает первый аргумент
  • otherUsers получает все остальные

Полезный пример: сумма любого количества чисел

Rest-параметры часто используют именно для таких задач.

function sum(...numbers) {
  return numbers.reduce((total, number) => total + number, 0);
}

console.log(sum()); // 0
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100

Без rest-параметров такую функцию пришлось бы писать заметно неудобнее.

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

Это важное синтаксическое правило.

Правильно:

function test(a, b, ...rest) {}

Неправильно:

// function test(...rest, a) {} // SyntaxError

JavaScript должен понимать, какие аргументы собрать в rest, поэтому после него уже не может быть обычных параметров.

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

Так тоже писать нельзя:

// function test(...a, ...b) {} // SyntaxError

У функции может быть только один rest-параметр.

Чем rest отличается от arguments

Раньше для похожих задач часто использовали arguments.

function show() {
  console.log(arguments);
}

show(1, 2, 3);

Но между ними есть важная разница:

  • rest - это настоящий массив
  • arguments - это специальный псевдомассив

С rest-параметром можно сразу делать так:

function sum(...numbers) {
  return numbers.reduce((total, number) => total + number, 0);
}

С arguments такой код уже неудобнее, потому что сначала пришлось бы преобразовывать значение в массив.

Rest-параметры работают и в стрелочных функциях

Это ещё один плюс: arguments у стрелочных функций нет, а rest-параметры работают нормально.

const sum = (...numbers) => {
  return numbers.reduce((total, number) => total + number, 0);
};

console.log(sum(1, 2, 3)); // 6

Поэтому в современном коде rest обычно удобнее, чем arguments.

Rest-параметры и spread - это не одно и то же

В обоих случаях используется ..., из-за этого их часто путают.

Но смысл разный:

  • rest собирает несколько значений в одно
  • spread, наоборот, раскрывает одно значение в несколько

Rest:

function logAll(...args) {
  console.log(args);
}

Spread:

const numbers = [1, 2, 3];

console.log(...numbers); // 1 2 3

То есть в параметрах функции ... обычно означает именно rest.

Когда это полезно

Rest-параметры особенно удобны, когда:

  • функция принимает любое количество аргументов
  • часть аргументов обязательна, а остальные дополнительные
  • нужно сразу работать с аргументами как с массивом
  • функция написана в стрелочном стиле и arguments недоступен

Пример:

function joinWords(separator, ...words) {
  return words.join(separator);
}

console.log(joinWords("-", "JavaScript", "это", "круто"));
// "JavaScript-это-круто"

Rest-параметры не считают обязательным количеством аргументов всё подряд

Если у функции есть обычные параметры перед rest, они заполняются как обычно, а rest получает остаток.

function show(first, second, ...rest) {
  console.log(first);
  console.log(second);
  console.log(rest);
}

show(1, 2, 3, 4, 5);
// 1
// 2
// [3, 4, 5]

Частые ошибки

Путать rest и spread

function logAll(...args) {
  console.log(args);
}

Здесь ...args не раскрывает значения, а собирает их в массив.

Ставить rest-параметр не в конец

// function test(...rest, value) {} // SyntaxError

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

Ожидать, что rest даст одно значение, а не массив

function test(...args) {
  console.log(args);
}

test(1, 2, 3); // [1, 2, 3]

Результат всегда массив, даже если аргумент всего один.

Забывать, что при отсутствии аргументов будет пустой массив

function test(...args) {
  console.log(args);
}

test(); // []

Это не undefined, а именно пустой массив.

Использовать arguments, когда нужен обычный массив

Если нужны методы массива и современный синтаксис, rest-параметры обычно удобнее и понятнее.

Быстрая памятка

  • ...args в параметрах функции означает rest-параметр
  • rest собирает оставшиеся аргументы в массив
  • если аргументов нет, получится []
  • rest-параметр должен быть последним
  • у функции может быть только один rest-параметр
  • rest отличается от arguments, потому что это настоящий массив
  • rest отличается от spread: rest собирает, spread раскрывает

Коротко

Rest-параметры в JavaScript позволяют собирать оставшиеся аргументы функции в массив. Главное, что стоит запомнить: они удобнее старого arguments, хорошо сочетаются со стрелочными функциями и особенно полезны там, где функция принимает произвольное количество значений.