Js Drip #2 Произвольное количество параметров с объектом arguments
Опубликовано Чт. 25 Декабрь 2014 в Translations
Вольный перевод JS Drip#2 Arbitrary Parameters with the arguments Object
В прошлый раз мы тебе рассказали про работу с аргументами по умолчанию. Это дает определенную гибкость при работе с аргументами, но что делать, если тебе нужно в функции обрабатывать столько аргументов, сколько в неё было передано? Например, нужна функция, которая складывает все переданные ей аргументы. Как это сделать?
function addAll () {
// Какой тут код?
}
// Должна вернуть 6
addAll(1, 2, 3);
// Должна вернуть 10
addAll(1, 2, 3, 4);
К счастью, JavaScript позволяет сделать это очень легко. Вся соль в объекте arguments
.
Хоть объект arguments
и не является массивом, но ведет себя как массив (читай: поддерживает индексацию и имеет
ссылку на связанную функцию), содержащий все аргументы, переданные функции.
function myFunc () {
console.log(arguments[0], arguments[1]);
}
// Выведет "param1" и "param2"
myFunc("param1", "param2");
Узнав о arguments
, ты можешь легко написать функцию сложения, обрабатывающую все переданне аргументы.
function addAll () {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum + arguments[i];
}
return sum;
}
// Вернет 6
addAll(1, 2, 3);
// Вернет 10
addAll(1, 2, 3, 4);
Но есть одна проблема. Надеюсь, ты не забыл, что arguments это на самом деле не массив? Проверить можно так:
function myFunc () {
console.log(Array.isArray(arguments));
}
//Выведет 'false'
myFunc('param');
Так что это не массив. Ты спросишь: "%usernames%, а есть ли разница?" А мы тебе ответим: да. Он не поддерживает
привычные методы массива, т.е. всякие push
,pop
, slice
, indexOf
и тому подобный sort
.
function sortArgs () {
// Это не сработает!
sorted = arguments.sort()
return sorted;
}
На это можно напороться, особенно если передавать содержимое arguments
в другую функцию, которая ожидает реальный массив.
Решение дьявольски простое в реализации, но чуть сложнее в понимании:
function sortArgs () {
// Конвертируем объект arguments в реальный массив
var args = [].slice.call(arguments);
// Теперь работает!
sorted = args.sort()
return sorted;
}
Рассмотрим решение по шагам:
- Мы создали пустой массив.
- Мы использовали метод
slice
у этого массива. - Мы использовали метод
call
, что бы сказатьslice
, что он должен обработать объект arguments, а не пустой массив.
Вызов slice
без указания начального индекса вернет исходный, не срезанный массив. В итоге получаем именно то, что и
хотели: реальный массив, содержащий все аргументы, переданные в функцию.