Параметры и аргументы

Параметры — переменные в определении функции, аргументы — реальные значения, передаваемые при вызове; JavaScript позволяет их число не совпадать и предоставляет богатые механизмы работы с ними.

Зачем нужно

Понимание разницы между параметрами и аргументами, а также знание значений по умолчанию, rest-параметров и объекта arguments необходимо для написания гибких, переиспользуемых функций с удобным API.

Где используется

  • Проектирование API функций и методов классов
  • Утилитарные функции с переменным числом аргументов
  • Деструктуризация параметров в колбэках и фабриках
  • Функции высшего порядка

Базовые параметры и аргументы

// name, age — параметры (в определении)
function greet(name, age) {
  return `${name}, ${age} лет`;
}

// 'Иван', 25 — аргументы (при вызове)
greet('Иван', 25); // 'Иван, 25 лет'

// Лишние аргументы игнорируются
greet('Анна', 30, 'extra'); // 'Анна, 30 лет'

// Недостающие параметры = undefined
greet('Пётр'); // 'Пётр, undefined лет'

Значения по умолчанию (Default Parameters)

function createUser(name, role = 'user', active = true) {
  return { name, role, active };
}

createUser('Иван');               // { name: 'Иван', role: 'user', active: true }
createUser('Анна', 'admin');      // { name: 'Анна', role: 'admin', active: true }
createUser('Пётр', 'user', false);// { name: 'Пётр', role: 'user', active: false }

// Значение по умолчанию — любое выражение
function log(msg, date = new Date) {
  console.log(`[${date.toISOString()}] ${msg}`);
}

Rest-параметры (...)

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

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

console.log(sum(1, 2, 3, 4)); // 10
console.log(sum);           // 0

// Комбинация с обычными параметрами
function log(level, ...messages) {
  console.log(`[${level}]`, ...messages);
}

log('INFO', 'Запуск', 'сервиса', 'OK'); // [INFO] Запуск сервиса OK

Деструктуризация параметров

// Объект
function displayUser({ name, age = 0, role = 'guest' }) {
  return `${name} (${age}), роль: ${role}`;
}

displayUser({ name: 'Иван', age: 25 });
// 'Иван (25), роль: guest'

// Массив
function first([head, ...tail]) {
  return { head, tail };
}

first([1, 2, 3]); // { head: 1, tail: [2, 3] }

// Вложенная деструктуризация
function getCity({ address: { city } }) {
  return city;
}

getCity({ address: { city: 'Москва' } }); // 'Москва'

Объект arguments (устаревший)

До ES6 для доступа ко всем аргументам использовался arguments:

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

// arguments — псевдомассив (нет .map, .forEach)
// Недоступен в стрелочных функциях
const arrow = () => console.log(arguments); // ReferenceError или outer arguments

// Современная альтернатива: rest-параметры
const newSum = (...args) => args.reduce((a, b) => a + b, 0);

Передача по значению vs по ссылке

// Примитивы — копия
function increment(n) {
  n++;
  return n;
}
let x = 5;
increment(x);
console.log(x); // 5 — не изменился

// Объекты — ссылка (мутация меняет оригинал)
function addRole(user) {
  user.role = 'admin'; // мутирует оригинал!
}
const user = { name: 'Иван' };
addRole(user);
console.log(user.role); // 'admin'

// Чистая функция: возвращаем новый объект
function addRolePure(user, role) {
  return { ...user, role };
}

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

1. Default параметр после rest

// SyntaxError: Rest parameter must be last formal parameter
function bad(a, ...rest, b = 1) {} // нельзя

// Правильно: rest — всегда последний
function good(a, b = 1, ...rest) {}

2. Мутация аргумента-объекта

function process(config) {
  config.timeout = 5000; // мутирует переданный объект!
  // Лучше: const cfg = { ...config, timeout: 5000 };
}

3. arguments в стрелочной функции

const fn = () => {
  console.log(arguments); // ошибка или захват из внешней области
};
// Используй rest: const fn = (...args) => args;

Связанные темы

Ресурсы