Остаточные параметры
Представьте пакет на кассе. Кассир не знает заранее, сколько покупок вы принесёте: две, десять или ни одной. Всё, что пробили, отправляется в один пакет, а дома вы достаёте покупки по одной.
С функциями бывает так же. Math.max принимает сколько угодно аргументов: и Math.max(3, 8), и Math.max(3, 8, 1, 9). Как написать свою функцию, которой можно передать любое число аргументов? Для этого в списке параметров ставят три точки:
function sum(...nums) {
let total = 0;
for (const n of nums) {
total += n;
}
return total;
}
console.log(sum(1, 2, 3), sum(5), sum()); // 6 5 0Давайте разберём по строкам:
function sum(...nums)объявляет один параметр с тремя точками перед именем.- При вызове
sum(1, 2, 3)вnumsпопадает массив[1, 2, 3]. - Цикл
for…ofобходит этот массив и складывает числа вtotal. - Вызов
sum(5)даёт массив из одного элемента, аsum()— пустой массив, и сумма равна0.
Остаточный параметр
Параметр с тремя точками перед именем называют остаточным параметром. В него попадают все аргументы вызова, для которых не нашлось обычного параметра. Это настоящий массив: у него есть length, его обходят через for…of и читают по индексу.
Тут аналогия с пакетом перестаёт работать. Пакет можно и не брать, а остаточный параметр есть всегда. Без аргументов nums — пустой массив, а не undefined, поэтому sum() вернула 0.
Параметры перед ним
Перед остаточным параметром можно поставить обычные. Они получают первые аргументы, а остаточный параметр собирает то, что осталось:
function describe(first, ...rest) {
console.log(first, rest.length);
}
describe("a", "b", "c"); // a 2
describe("a"); // a 0В первом вызове first получил "a", а в rest попали "b" и "c". Во втором вызове для rest аргументов не осталось, и он пустой. Так пишут функции, у которых первый аргумент особый, а за ним идёт сколько угодно значений.
Остаточный параметр может быть только последним. Иначе непонятно, где заканчиваются его аргументы, и function f(...rest, last) не запустится. Node и Chrome сообщают:
SyntaxError: Rest parameter must be last formal parameterСобрать и разложить
В уроке о ссылках три точки раскладывали массив на элементы. Здесь они работают в обратную сторону: собирают аргументы в массив. Запись одна, а роли у неё две:
- в массиве и в вызове функции три точки раскладывают элементы;
- в списке параметров три точки собирают аргументы.
Роль подсказывает место: стоят ли три точки в объявлении функции или там, где массив используют. На собеседовании часто просят объяснить разницу между остаточными параметрами и синтаксисом расширения. Короткий ответ: остаточный параметр собирает аргументы в массив, а расширение раскладывает массив на элементы.
Частая ошибка
Готовый массив передали функции с остаточным параметром:
const prices = [1, 2, 3];
console.log(sum(prices)); // ✗Ошибки нет, но программа печатает 01,2,3, а не 6. Массив пришёл одним аргументом, и nums стал массивом из одного элемента — массива prices. При сложении с числом массив превратился в строку "1,2,3", и 0 склеился с ней.
Чтобы передать элементы по отдельности, разложите массив в вызове: sum(...prices) возвращает 6.
Главное
- Остаточный параметр
...numsсобирает оставшиеся аргументы вызова в массив. - Без аргументов он пустой массив, а не
undefined. - Остаточный параметр стоит последним в списке параметров.
- В параметрах три точки собирают аргументы, а в массиве и в вызове раскладывают элементы.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.