В теле функции идентификатор arguments всегда имеет особый смысл; arguments – это специальное свойство объекта вызова, ссылающееся на объект, известный как объект Arguments. Объект Arguments – это нечто вроде массива (см. раздел 7.8), позволяющего извлекать переданные функции значения по номеру, а не по име_ ни. Объект Arguments также определяет дополнительное свойство callee, которое описано в следующем разделе.
Хотя JavaScript_функция определяется с фиксированным количеством имено_ ванных аргументов, при вызове ей может быть передано любое их число. Объект Arguments обеспечивает полный доступ к значениям аргументов, даже если у не_ которых из них нет имени. Предположим, что была определена функция f, кото_ рая требует один аргумент, x. Если вызвать эту функцию с двумя аргументами, то первый будет доступен в функции по имени параметра x или как arguments[0]. Второй аргумент доступен только как arguments[1]. Кроме того, как и у всех мас_ сивов, у arguments имеется свойство length, указывающее на количество содержа_ щихся в массиве элементов. То есть в теле функции f, вызываемой с двумя аргу_ ментами, arguments.length имеет значение 2.
Объект arguments может использоваться с самыми разными целями. Следующий пример показывает, как с его помощью проверить, была ли функция вызвана с правильным числом аргументов, – ведь JavaScript этого за вас не сделает:
function f(x, y, z)
{
// Сначала проверяется, правильное ли количество аргументов передано if (arguments.length != 3) {
throw new Error("функция f вызвана с " + arguments.length + "аргументами, а требуется 3.");
}
// А теперь сам код функции...
}
Объект arguments иллюстрирует важную возможность JavaScript_функций: они могут быть написаны таким образом, чтобы работать с любым количеством аргу_ ментов. Далее приводится пример, показывающий, как можно написать про_ стую функцию max(), принимающую любое число аргументов и возвращающую значение самого большого из них (аналогично ведет себя встроенная функция
Math.max()):
function max(/*...*/)
{
var m = Number.NEGATIVE_INFINITY;
// Цикл по всем аргументам, поиск и сохранение наибольшего из них for(var i = 0; i < arguments.length; i++)
if (arguments[i] > m) m = arguments[i];
// Возвращаем максимальный
return m;
}
var largest = max(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6);
8.2. Аргументы функций
Функции, подобные этой и способные принимать произвольное число аргумен_ тов, называются функциями с переменным числом аргументов (variadic func' tions, variable arity functions или varargs functions). Этот термин возник вместес появлением языка программирования C.
Обратите внимание: функции с переменным числом аргументов не должны до_ пускать возможность вызова с пустым списком аргументов. Будет вполне разум_ ным использовать объект arguments[] при написании функции, ожидающей по_ лучить фиксированное число обязательных именованных аргументов, за кото_ рыми может следовать произвольное число необязательных неименованных ар_ гументов.
Не следует забывать, что arguments фактически не является массивом – это объект Arguments. В каждом объекте Arguments имеются пронумерованные элементы мас_ сива и свойство length, но с технической точки зрения – это не массив. Лучше рас_ сматривать его как объект, имеющий некоторые пронумерованные свойства. Спе_ цификация ECMAScript не требует от объекта Arguments реализации какого_либо специфического для массива поведения. Хотя, например, допускается присваи_ вать значение свойству arguments.length, ECMAScript не требует этого для реаль_ ного изменения числа элементов массива, определенных в объекте. (Особое пове_ дение свойства length для настоящих объектов Array описывается в разделе 7.6.3.)
У объекта Arguments есть одна очень необычная особенность. Когда у функции име_ ются именованные аргументы, элементы массива объекта Arguments являются си_ нонимами локальных переменных, содержащих аргументы функции. Массив ar_ guments[] и именованные аргументы – это два разных средства обращения к одной переменной. Изменение значения аргумента через имя аргумента меняет значе_ ние, извлекаемое через массив arguments[]. Изменение значения аргумента через массив arguments[] меняет значение, извлекаемое по имени аргумента. Например:
function f(x) {
print(x);
// Выводит начальное значение аргумента
arguments[0] = null; //
Изменяя элементы массива, мы также изменяем x
print(x);
//
Теперь выводит "null"
}
Определенно, это не совсем то поведение, которое можно было бы ожидать от на_ стоящего массива. В этом случае arguments[0] и x могли бы ссылаться на одно и то же значение, но изменение одной ссылки не должно оказывать влияния на другую.
Наконец, следует учитывать, что arguments – это всего лишь обычный JavaScript_ идентификатор, а не зарезервированное слово. Если функция определит аргу_ мент или локальную переменную с таким же именем, объект Arguments станет не_ доступным. По этой причине следует считать слово arguments зарезервированным и стараться избегать создавать переменные с таким именем.