Перейти к содержимому
Теория · Массивы · урок 9 из 13

Остаточные параметры

Представьте пакет на кассе. Кассир не знает заранее, сколько покупок вы принесёте: две, десять или ни одной. Всё, что пробили, отправляется в один пакет, а дома вы достаёте покупки по одной.

С функциями бывает так же. Math.max принимает сколько угодно аргументов: и Math.max(3, 8), и Math.max(3, 8, 1, 9). Как написать свою функцию, которой можно передать любое число аргументов? Для этого в списке параметров ставят три точки:

JavaScript
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

Давайте разберём по строкам:

  1. function sum(...nums) объявляет один параметр с тремя точками перед именем.
  2. При вызове sum(1, 2, 3) в nums попадает массив [1, 2, 3].
  3. Цикл for…of обходит этот массив и складывает числа в total.
  4. Вызов sum(5) даёт массив из одного элемента, а sum() — пустой массив, и сумма равна 0.

Остаточный параметр

Параметр с тремя точками перед именем называют остаточным параметром. В него попадают все аргументы вызова, для которых не нашлось обычного параметра. Это настоящий массив: у него есть length, его обходят через for…of и читают по индексу.

Тут аналогия с пакетом перестаёт работать. Пакет можно и не брать, а остаточный параметр есть всегда. Без аргументов nums — пустой массив, а не undefined, поэтому sum() вернула 0.

Параметры перед ним

Перед остаточным параметром можно поставить обычные. Они получают первые аргументы, а остаточный параметр собирает то, что осталось:

JavaScript
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 сообщают:

TEXT
SyntaxError: Rest parameter must be last formal parameter

Собрать и разложить

В уроке о ссылках три точки раскладывали массив на элементы. Здесь они работают в обратную сторону: собирают аргументы в массив. Запись одна, а роли у неё две:

  • в массиве и в вызове функции три точки раскладывают элементы;
  • в списке параметров три точки собирают аргументы.

Роль подсказывает место: стоят ли три точки в объявлении функции или там, где массив используют. На собеседовании часто просят объяснить разницу между остаточными параметрами и синтаксисом расширения. Короткий ответ: остаточный параметр собирает аргументы в массив, а расширение раскладывает массив на элементы.

Частая ошибка

Готовый массив передали функции с остаточным параметром:

JavaScript
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 и подпишись на канал — откроются все уроки.

Войти другим способом