Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Давайте попробуем реализовать очень простую функцию, суммирующую числа. Для начала определим функцию sum()
, принимающую на вход два числа и возвращающую их сумму:
const sum = (a, b) => a + b;
sum(1, 2); // 3
sum(-3, 10); // 7
Пока всё просто и понятно. Сложности возникают при дополнительных требованиях: что, если захотим суммировать не два, а три числа? Или пять, или даже десять? Писать для обработки каждого случая отдельную функцию — очевидно плохой вариант:
const sumOfTwo = (a, b) => a + b;
const sumOfTree = (a, b, c) => a + b + c;
const sumOfTen = (a, b, c, d, e, f, g, h, i, j) => a + b + c + d + e + f + g + h + i + j; // фух...
// const sumoOfThousand = ???
// const sumOfMillion = ???
Надо, чтобы единая функция могла работать с разным количеством аргументов. Как это сделать?
Можно заметить, что в стандартной библиотеке JavaScript существуют функции, которые могут принимать разное количество аргументов. Например, сигнатура функции Math.max() определяется так:
Math.max([value1[, value2[, ...]]])
Она говорит нам о том, что в Math.max()
можно передать любое количество элементов и они не обязательны:
Math.max(10, 20); // 20
Math.max(10, 20, 30); // 30
Math.max(10, 20, 30, 40, 50); // 50
Math.max(-10, -20, -30); // -10
С точки зрения вызова — ничего необычного, просто разное число аргументов. А вот определение функции с переменным числом аргументов выглядит необычно:
const func = (...params) => {
// params — это массив, содержащий все
// переданные при вызове функции аргументы
console.log(params);
};
func(); // => []
func(9); // => [9]
func(9, 4); // => [9, 4]
func(9, 4, 1); // => [9, 4, 1]
func(9, 4, 1, -3); // => [9, 4, 1, -3]
https://repl.it/@hexlet/js-functions-rest-operator-rest-parameters
Символ троеточия ...
перед именем формального параметра в определении функции обозначает rest-оператор. Запись ...params
в определении func()
из примера выше означает буквально следующее: "все переданные при вызове функции аргументы поместить в массив params
".
Если вовсе не передать аргументов, то массив params
будет пустым:
func(); // => []
В функцию можно передать любое количество аргументов — все они попадут в массив params
:
func(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Аргументы могут быть любого типа — числа, строки, массивы и др.:
func(1, 2, 'hello', [3, 4, 5], true);
// => [1, 2, 'hello', [3, 4, 5 ], true]
Теперь у нас достаточно знаний, чтобы с помощью rest-оператора переписать нашу функцию sum()
так, чтобы она умела суммировать любое количество чисел (а не только два числа, как сейчас):
const sum = (...numbers) => {
// По умолчанию 0, так как сумма ничего это 0
let result = 0;
for (let num of numbers) {
result += num;
}
return result;
};
sum(); // 0
sum(10); // 10
sum(10, 4); // 14
sum(8, 10, 4); // 22
https://repl.it/@hexlet/js-functions-rest-operator-sum
В таком контексте массив можно считать как "необязательные аргументы", которые можно либо вовсе не передавать, либо передавать столько, сколько хочешь. А что, если мы захотим, чтобы функция имела два обыкновенных ("обязательных") именованных параметра, а остальные были необязательными и сохранялись в rest-массиве? Всё просто: при определении функции сначала указываем стандартные именованные формальные параметры (например, a
и b
) и в конце добавляем rest-массив:
const func = (a, b, ...params) => {
// параметр 'a' содержит первый аргумент
console.log(`a -> ${a}`);
// параметр 'b' содержит второй аргумент
console.log(`b -> ${b}`);
// params содержит все остальные аргументы
console.log(params);
};
func(9, 4);
// => a -> 9
// => b -> 4
// => []
func(9, 4, 1);
// => a -> 9
// => b -> 4
// => [1]
func(9, 4, 1, -3);
// => a -> 9
// => b -> 4
// => [1, -3]
func(9, 4, 1, -3, -5);
// => a -> 9
// => b -> 4
// => [1, -3, -5]
https://repl.it/@hexlet/js-functions-rest-operator-many-more-args
То же можно сделать и для одного аргумента:
const func = (a, ...params) => {
// ...
};
и для трёх:
const func = (a, b, c, ...params) => {
// ...
};
Эту идею можно продолжать и дальше, делая обязательными то количество аргументов, которое требуется. Единственное ограничение: rest-оператор может быть использован только для последнего параметра. То есть такой код синтаксически неверен:
const func = (...params, a) => {
// ...
};
И такой тоже:
const func = (a, ...params, b) => {
// ...
};
Именно поэтому оператор называется rest, то есть он организует хранение "остальных" ("оставшихся", последних) параметров.
Вам ответят команда поддержки Хекслета или другие студенты.
Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
или войти в аккаунт
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт