Опциональные параметры

В JavaScript функции могут быть вызваны с любым числом аргументов, независимо от того, сколько параметров было объявлено. Это создаёт гибкость, но требует механизма для работы с опциональными параметрами — параметрами, которые могут быть опущены при вызове функции.

Объявление опциональных параметров

В современном JavaScript опциональные параметры задаются с помощью значения по умолчанию:

function greet(name = "Гость") {
    console.log(`Привет, ${name}!`);
}

greet();       // Привет, Гость!
greet("Анна"); // Привет, Анна!

Если аргумент не передан, используется значение по умолчанию. Этот способ предпочтителен, так как делает код более читаемым и защищает от undefined.

Проверка аргументов вручную

До появления значений по умолчанию часто использовалась проверка аргументов внутри функции:

function multiply(a, b) {
    if (b === undefined) {
        b = 1;
    }
    return a * b;
}

multiply(5);    // 5
multiply(5, 2); // 10

Такой подход работает, но делает код более громоздким и менее очевидным.

Опциональные параметры и arguments

Все функции имеют локальную переменную arguments, содержащую все переданные аргументы. Это позволяет создавать функции с переменным числом параметров:

function sumAll() {
    let total = 0;
    for (let i = 0; i < arguments.length; i++) {
        total += arguments[i];
    }
    return total;
}

sumAll(1, 2, 3, 4); // 10

Однако использование arguments считается устаревшим в современном JavaScript, на смену приходит оператор rest.

Оператор rest для опциональных и вариативных параметров

Синтаксис ... позволяет собирать остаток аргументов в массив:

function sum(first, ...rest) {
    let total = first;
    for (const num of rest) {
        total += num;
    }
    return total;
}

sum(1, 2, 3, 4); // 10

Преимущество оператора rest — явное указание, какие параметры обязательны, а какие — вариативны, без необходимости вручную проверять arguments.length.

Опциональные параметры в TypeScript

TypeScript расширяет возможности JavaScript и позволяет явно указывать опциональные параметры с помощью знака ?:

function greet(name?: string) {
    if (name) {
        console.log(`Привет, ${name}!`);
    } else {
        console.log("Привет, Гость!");
    }
}

greet();       // Привет, Гость!
greet("Анна"); // Привет, Анна!

С точки зрения TypeScript, это повышает безопасность типов и предотвращает ошибки при вызове функции без аргументов.

Особенности работы с undefined

Даже если параметр объявлен без значения по умолчанию, передача undefined эквивалентна его отсутствию:

function greet(name = "Гость") {
    console.log(`Привет, ${name}!`);
}

greet(undefined); // Привет, Гость!
greet(null);      // Привет, null!

Важно различать undefined и null: undefined активирует значение по умолчанию, null — нет.

Опциональные параметры в комбинации с обязательными

Параметры с дефолтными значениями или опциональные должны идти после обязательных параметров. Иначе синтаксис будет некорректным:

function createUser(name, age = 18) {
    return { name, age };
}

createUser("Иван");       // { name: "Иван", age: 18 }
createUser("Иван", 25);   // { name: "Иван", age: 25 }

Попытка поставить обязательный параметр после опционального приведёт к ошибке:

function wrong(age = 18, name) {} // Ошибка

Использование объектов для гибких опциональных параметров

Если функция имеет множество опциональных параметров, удобно передавать их через объект:

function configure(options) {
    const { width = 100, height = 200, color = "red" } = options;
    console.log(width, height, color);
}

configure({ width: 150 }); // 150 200 red
configure({});             // 100 200 red

Это делает код более читаемым и предотвращает ошибки при изменении числа параметров.

Опциональные параметры в стрелочных функциях

Стрелочные функции поддерживают значения по умолчанию так же, как обычные функции:

const greet = (name = "Гость") => `Привет, ${name}!`;

greet();       // Привет, Гость!
greet("Анна"); // Привет, Анна!

Вариативные параметры с оператором rest также работают в стрелочных функциях:

const sum = (...numbers) => numbers.reduce((a, b) => a + b, 0);

sum(1, 2, 3); // 6

Взаимодействие опциональных параметров с деструктуризацией

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

function display({ name = "Гость", age = 18 } = {}) {
    console.log(`${name}, ${age}`);
}

display({ name: "Анна" }); // Анна, 18
display();                  // Гость, 18

Использование значения по умолчанию для всего параметра {} предотвращает ошибку при вызове функции без аргументов.

Практические рекомендации

  • Значения по умолчанию упрощают работу с опциональными параметрами и повышают читаемость.
  • Для функций с большим числом опциональных параметров предпочтительно использовать объект.
  • Rest-параметры удобны для вариативных функций, где количество аргументов заранее неизвестно.
  • В TypeScript рекомендуется явно указывать опциональность с ? для безопасного контроля типов.