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, хорошо сочетаются со стрелочными функциями и особенно полезны там, где функция принимает произвольное количество значений.