|
Остаточные аргументы и оператор расширения
Далее, несколько
слов об остаточных параметрах функций. В JavaScript можно задавать
функции, принимающие неограниченное число аргументов. Например, стандартные
функции Math.max и Math.min могут работать
с произвольным числом входных параметров. Как объявлять такие функции? Это
делается с помощью такого синтаксиса:
function sumAll(...args) {
let sum = 0;
for(let val of args)
sum += val;
return sum;
}
Здесь мы тремя
точками говорим буквально следующее: нужно взять все переданные аргументы и
поместить их в массив args. Далее уже идет работа с самим
массивом.
console.log( sumAll(1, 2) );
console.log( sumAll(1, 2, 3, 4) );
Кстати,
вспоминая работу с массивами, мы можем записать эту функцию гораздо короче:
function sumAll(...args) {
return args.reduce((prevVal, value) => prevVal += value, 0);
}
Вот она сила и
мощь языка JavaScript! Но почему
массив этих аргументов называется остаточными параметрами? Дело в том, что мы
можем комбинировать обычные аргументы и такой массив, например:
function sumAll(arg1, arg2, ...args) {
return arg1 + arg2 + args.reduce((prevVal, value) => prevVal += value, 0);
}
и остаточные
аргументы всегда должны быть записаны последними – в массив args собирается все,
что мы передаем помимо первых двух аргументов. Например, при таком вызове:
console.log( sumAll(1, 2) );
массив args будет пустым. А
при таком:
console.log( sumAll(1, 2, 3, 4) );
содержать
значения 3 и 4 – остаточные параметры. Вот так это работает.
В
противоположность остаточным аргументам, когда множество переданных значений
помещаются в массив, в JavaScript существует оператор расширения,
который разворачивает массив в набор отдельных значений. Как он записывается и
зачем он нужен? Давайте опять обратимся к стандартной функции Math.max. Она находит
максимальное значение из переданных значений. Но, что если наши значения
хранятся в массиве?
let items = [1, 2, 3, 4, 5];
При вызове
let max = Math.max(items);
console.log( max );
получим значение
NaN. Конечно, мы
могли бы передать каждый элемент массива вот так:
let max = Math.max(items[0], items[1], ..., items[4]);
но это крайне
неудобно и теряется гибкость кода. Гораздо удобнее воспользоваться оператором
расширения, который все это сделает автоматически:
let max = Math.max(...items);
И теперь мы
видим верное значение 5. Мы даже можем записать так сразу два массива:
let items = [1, 2, 3, 4, 5];
let digs = [-1, 0, 6, 10, 101];
let max = Math.max(...items, ...digs);
и найти максимум
среди всех этих элементов. Или, комбинировать их с обычными значениями:
let max = Math.max(...items, 1000, ...digs, 0);
Кстати,
используя этот механизм, можно делать объединение массивов:
let comp = [...items, ...digs];
console.log( comp );
А также
вписывать туда отдельные значения:
let comp = [...items, -1, -2, -3, ...digs];
Как видите – это
очень гибкий механизм. И он работает не только с массивами, но с любыми
итерируемыми (перебираемыми) данными, например, со строками:
let letters = [..."Привет"];
console.log( letters );
Вам может
показаться, что один и тот же оператор … используется как для остаточных
параметров, так и для расширения. Но, в действительности, здесь есть четкое
разделение:
-
если
оператор … записан при объявлении функции в списке его аргументов, то это для
сбора остаточных аргументов;
-
во
всех остальных случаях … это оператор расширения итерируемых объектов.
|