Когда у нас есть функция, которой передаются один или два аргумента, довольно легко получить аргументы и делать с ними то, что мы хотим. Но возникает проблема, когда, например, функции нужно передать до или более 4 аргументов.

Возьмем приведенную ниже функцию sum в качестве примера:

var sum = function (a, b, c, d) {
  return a + b + c + d;
};
sum(1, 2, 3, 4);

Существует большая вероятность того, что это станет очень громоздким довольно быстро. Просто представьте, что у вас более четырех аргументов, или, если вы не можете быть уверены, это может быть связано с тем, что аргументы определяются во время выполнения. Чего мы действительно хотим добиться, так это динамически получить все аргументы, переданные в функцию.

Чтобы перейти к основной проблеме:

Как вы динамически получаете все аргументы функции?

Объект аргументов.

Это один из способов делать то, что мы хотим. Используя объект arguments, JavaScript предоставил нам возможность динамически получать все аргументы, передаваемые в функцию. Объект arguments — это массивоподобный объект, содержащий элементы, соответствующие аргументам, переданным в функцию.

Внутри любой функции объект arguments можно использовать для получения подобного массиву списка всех аргументов, переданных в функцию. Это нативный объект JavaScript, поэтому его не нужно определять заранее, он доступен как локальная переменная во всех нестрелочных функциях. Доступ к элементам в аргументах осуществляется путем вызова их индекса, индекс начинается с 0.

Давайте посмотрим, как мы можем использовать объект arguments в нашей функции sum.

let sum = function () {
  //result: { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 } //array-like
  console.log(arguments);
  //result: 1
  console.log(arguments[0]);
  //result: 2
  console.log(arguments[1]);
  //calculating the sum of the arguments
  let total = 0;
  for (var i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  console.log(total);
};
sum(1, 2, 3, 4, 5); //pass as many arguments as you require

Внутри нашей функции sum автоматически присутствует переменная arguments. Этого не будет, если sum будет стрелочной функцией. Эта переменная arguments содержит все аргументы, которые мы передали в нашу функцию sum, и мы можем получить любой из этих отдельных аргументов, используя его индекс, то есть так же, как мы получаем значения элементов в массиве. В приведенном выше фрагменте кода мы получили аргументы с индексами 0 и 1.

Обратите внимание, что объект arguments не является массивом, хотя он почти идентичен массиву. Длина — это единственное свойство массива, которое у него есть.

Есть еще один способ.

Остальной параметр

Используя остальные параметры, введенные в ES2016, мы также можем это сделать. Параметр rest позволяет нам представить неизвестное количество аргументов в виде массива, поэтому мы можем использовать его для динамического получения всех аргументов, переданных в функцию. Остальной оператор представлен тремя точками (…), за которыми следует имя по нашему выбору.

Продолжая использовать нашу функцию суммы в качестве примера, давайте воспользуемся оставшимся параметром, чтобы увидеть, как она работает. Обратите внимание, мы также переключились на функцию стрелки.

let sum = (...valuesToAdd) => {
  //result: [ 1, 2, 3, 4, 5 ] //real array
  console.log(valuesToAdd);
  //result: 3
  console.log(valuesToAdd[2])
  //calculating the sum of the arguments
  let total = 0;
  for (var i = 0; i < valuesToAdd.length; i++) {
    total += valuesToAdd[i];
  }
  return total;
}
sum(1, 2, 3, 4, 5);  //pass as many arguments as you require

Оператор rest делает доступными в виде массива все аргументы, переданные нашей функции sum. К каждому аргументу можно получить доступ, используя его индекс, как обычный массив. В приведенном выше фрагменте кода мы получили аргумент с индексом 2.

Как упоминалось ранее, объект arguments не является реальным массивом, но параметр rest является массивом, это означает, что для него могут быть вызваны такие методы, как sort, map, pop, почти все методы массива. Объект arguments должен быть преобразован в настоящий массив, прежде чем мы сможем вызвать для него любой из методов массива.

Чтобы продемонстрировать это, в приведенном ниже коде показан результат, который мы получаем, когда используем метод массива pop как для оставшегося параметра, так и для объекта аргументов. Он отлично работает с остальным параметром, но не с объектом arguments.

let arrayTest = function (...values) {
  values.pop();
  //result: [1, 5, 6, 7, 3, 2]
  console.log(values);
  
  //result: TypeError: arguments.pop is not a function
  console.log(arguments.pop());
}
arrayTest(1, 5, 6, 7, 3, 2, 4);

Порядок списка аргументов при использовании остаточного параметра

Параметр rest должен быть последним, если вы хотите использовать его с другими аргументами. В списке аргументов функции параметр rest начинает брать элементы своего массива с позиции аргумента, который он занимает в списке аргументов, до последнего.

Правильное использование параметра rest с другими аргументами:

let correct = (x, y, ...values) => {
  // result: 1
  console.log(x);
  //result: 5
  console.log(y);

  //begins from the third argument to the last
  //result: [6, 7, 3, 2, 4]
  console.log(values);
}
correct(1, 5, 6, 7, 3, 2, 4);

Неправильное использование:

let inCorrect = (...values, y) => {
  //result: Rest parameter must be last formal parameter
}
inCorrect(1, 5, 6, 7, 3, 2, 4);

Неправильное использование параметра rest с другими аргументами приведет к ошибке:параметр rest должен быть последним формальным параметром. Если вам нужно использовать оставшийся параметр как часть списка аргументов, он должен быть последним.

Объект arguments раньше был моим методом goto для выполнения задачи динамического получения всех аргументов функции, но это изменилось с момента введения остальных параметров. Если вы еще не использовали его, попробуйте, возможно, он вам тоже понравится.

Документация — хорошее место для начала, если вы хотите узнать больше.

Спасибо, что прочитали это. Я надеюсь, что вы найдете это полезным.