|
Передача в функцию параметров через arguments или ...rest на языке JavaScript: в чем отличие?
Отличие между `arguments` и `...rest` (остаточные параметры) — это отличие устаревшего массиво-подобного объекта (array-like object) от настоящего современного массива.
Вот ключевые различия:
1. Тип данных (самое важное)
arguments — это массиво-подобный объект (iterable object). У него есть индекс [0], [1] и свойство length, но нет методов массива (map, filter, reduce, forEach, pop и т. д).
...rest — это настоящий массив (Array). С ним можно работать напрямую, используя все встроенные методы.
// arguments (НЕ массив) function oldFunc() { console.log(arguments.map); // undefined (метода нет!) console.log(Array.isArray(arguments)); // false
}
// ...rest (НАСТОЯЩИЙ массив) function newFunc(...args) { console.log(args.map); // function map() { ... } console.log(Array.isArray(args)); // true
}
2. Синтаксис объявления
`arguments` доступен внутри любой функции (кроме стрелочных) без явного объявления. Он просто существует.
`...rest` нужно явно указывать в списке параметров функции, ставя три точки перед именем (`...args`), и он должен быть последним параметром.
// OK: rest последний function sum(prefix, ...numbers) { ... }
// ОШИБКА: rest не может идти перед другими параметрами function sum(...numbers, prefix) { ... }
3. Работа в стрелочных функциях
- `arguments` в стрелочных функциях не работает (выдаст ошибку или ссылку на внешнюю функцию, если она есть).
- `...rest` отлично работает в стрелочных функциях, так как это обычный параметр.
const arrowOld = () => { console.log(arguments); // ReferenceError: arguments is not defined
};
const arrowNew = (...args) => { console.log(args); // [1, 2, 3] - всё работает
};
arrowNew(1, 2, 3);
4. Влияние на длину функции (свойство `.length`)
- `arguments` не влияет на официальное количество ожидаемых параметров.
- `...rest` не учитывается в свойстве `length` функции (считаются только явные параметры до него).
function a(a, b) { console.log(arguments.length); }
a.length; // 2 (ожидаем 2 параметра)
function b(a, b, ...rest) { }
b.length; // 2 (rest игнорируется)
5. Работа с частичными параметрами
`arguments` захватывает все переданные аргументы без исключений.
`...rest` захватывает только "остаток" (излишек) аргументов, позволяя выделить первые несколько параметров по имени.
function show(first, second, ...rest) { console.log(first); // 1 console.log(second); // 2 console.log(rest); // [3, 4, 5] (только лишние)
}
show(1, 2, 3, 4, 5);
Итоговая таблица:
| Характеристика |
arguments |
...rest |
| Тип |
Псевдомассив (не имеет методов) |
Настоящий массив (Array) |
| Работа в стрелках |
❌ Недоступен |
✅ Доступен |
| Позиция в параметрах |
Всегда все аргументы |
Только "хвост" аргументов |
| Актуальность стандарта |
Устаревший (deprecated) |
Современный (ES6+) |
| Производительность |
Медленнее (оптимизируется хуже) |
Быстрее и оптимизируется |
Что использовать в 2026 году? Всегда используйте `...rest`. `arguments` оставлен только для поддержки старого кода. Если вам вдруг понадобилось использовать `arguments` (например, в легаси-коде) и нужно применить метод массива, делайте преобразование:
function legacy() { // Превращаем псевдомассив в настоящий массив const args = Array.from(arguments); // или const args = [...arguments]; args.map(x => x * 2);
}
Но лучше просто переписать функцию на `(...args)`.
[Синтаксис ...spread]
Ранее было показано поведение оператора ...rest (остаточные параметры), но для передачи параметров функцию также существует ...spread (оператор расширения). Визуально они выглядят одинаково (три точки), но решают прямо противоположные задачи. И это иногда вызывает путаницу в понимании.
Давайте четко разграничим:
...rest (остаточные параметры) — собирает элементы в массив
Где используется: в объявлении функции, в списке параметров. Задача: взять «оставшиеся» аргументы и сложить их в настоящий массив.
// REST — собирает разрозненные аргументы в кучу (массив) function logAll(first, second, ...rest) { console.log(first); // 1 console.log(second); // 2 console.log(rest); // [3, 4, 5] — собрали остаток
}
logAll(1, 2, 3, 4, 5);
...spread (оператор расширения) — разворачивает массив на отдельные элементы
Где используется: при вызове функции, в литералах массивов/объектов. Задача: взять массив (или объект) и «распаковать» его содержимое наружу.
// SPREAD — разворачивает массив в список значений const numbers = [3, 4, 5];
// Без spread: передаем массив как один аргумент
console.log(numbers); // [3, 4, 5]
// Со spread: массив "рассыпается" на отдельные аргументы
console.log(...numbers); // 3 4 5 (отдельные числа)
Яркие примеры использования ...spread:
1. Вызов функции с массивом вместо списка аргументов
const scores = [10, 20, 30];
// Без spread — передается один массив Math.max(scores); // NaN (Math.max ожидает числа, не массив)
// Со spread — массив превращается в список чисел Math.max(...scores); // 30 (работает!)
2. Создание нового массива (копирование / объединение)
const arr1 = [1, 2]; const arr2 = [3, 4];
// Создаем новый массив, разворачивая старые внутрь const combined = [...arr1, ...arr2]; // [1, 2, 3, 4] const copy = [...arr1]; // [1, 2] (поверхностная копия)
3. Создание нового объекта (копирование / слияние)
const user = { name: 'Alex', age: 25 }; const updated = { ...user, age: 26, city: 'Moscow' };
console.log(updated); // { name: 'Alex', age: 26, city: 'Moscow' }
4. Сравнение в одном месте (функция)
Самый частый вопрос на собеседованиях:
// REST — в ОБЪЯВЛЕНИИ функции (слева от =>) function sum(...numbers) { // REST: собирает аргументы в массив return numbers.reduce((a, b) => a + b, 0);
}
// SPREAD — при ВЫЗОВЕ функции (справа от =>) const values = [1, 2, 3, 4];
console.log(sum(...values)); // SPREAD: разворачивает массив в аргументы // Сначала spread развернул [1,2,3,4] в 1,2,3,4 // Потом rest собрал их обратно в массив numbers // Результат: 10
5. Еще один трюк (превращение строки в массив)
const str = 'Hello';
// Spread разворачивает строку в отдельные символы
console.log([...str]); // ['H', 'e', 'l', 'l', 'o']
// То же самое, но старый способ
console.log(str.split('')); // ['H', 'e', 'l', 'l', 'o']
Коротко для запоминания:
...rest (в параметрах) = «Я возьму всё лишнее и положу в массив». ...spread (везде остальное) = «Я вытащу всё из массива/объекта наружу».
Если увидели три точки внутри скобок ( ) — это rest. Если увидели три точки внутри [ ] или { } или при вызове — это spread. |