Как собрать неопределённое количество аргументов функции в JavaScript и работать с ними
Что проверяют
Знаете ли вы разницу между rest-параметрами и объектом arguments и понимаете ли, почему в современном коде используют первое. Следом спрашивают, чем rest отличается от spread, или просят написать debounce.
Как отвечать
Основной способ это rest-параметры:
function sum(...nums):numsнастоящий массив, на нём сразу работаютreduce,map,filter. Rest-параметр может быть только один и только последним:function log(level, ...messages);fn.length: не учитывает rest-параметр и параметры со значением по умолчанию, это важно для каррирования и библиотек, которые смотрят на арность;- стрелочные функции: своего
argumentsу них нет, внутри стрелки он берётся из внешней обычной функции. Поэтому в стрелке собирать аргументы можно только через rest; arguments: псевдомассив сlengthи индексами, но без методов массива. Превращается в массив черезArray.from(arguments)или[...arguments]. В нестрогом режиме он ещё и связан с именованными параметрами: присваивание одному меняет другое.
Rest и spread выглядят одинаково, но работают в обратные стороны: rest в объявлении собирает значения в массив, spread при вызове раскладывает массив в аргументы, как в Math.max(...values). На очень больших массивах spread упирается в лимит аргументов движка и падает с RangeError, там надёжнее reduce.
Типичная задача на фронтенде: обёртка, которая сохраняет и аргументы, и this.
function debounce(fn, ms) {
let t;
return function (...args) {
clearTimeout(t);
t = setTimeout(() => fn.apply(this, args), ms);
};
}В TypeScript rest типизируется массивом или кортежем: (...args: [string, number]) или Parameters<typeof fn>.
Где спотыкаются
Называют ... в параметрах оператором расширения. Это синтаксис остаточных параметров, а spread относится к вызову и литералам.
Используют arguments внутри стрелочной функции и получают аргументы внешней функции или ReferenceError на верхнем уровне модуля.
Делают возвращаемую функцию в обёртке стрелочной. Тогда this берётся из места объявления, и метод объекта, пропущенный через debounce, теряет свой объект.