arguments
— это имя локального объекта в виде массива, доступного внутри каждой функции. Это странно, часто игнорируется, но является источником большого количества волшебства программирования; все основные библиотеки JavaScript используют мощь объекта arguments
. С этим должен познакомиться каждый программист JavaScript.
Внутри любой функции вы можете получить к ней доступ через переменную: arguments
, и она содержит массив всех аргументов, которые были переданы функции при ее вызове. На самом деле это не массив JavaScript; typeof arguments
будут возвращать значение: "object"
. Вы можете получить доступ к отдельным значениям аргумента через индекс массива, и он имеет свойство length
как и другие массивы, но у него нет стандартных методов Array
таких как push
и pop
.
Создать гибкие функции
Хотя это может показаться ограниченным, arguments
— очень полезный объект. Например, вы можете создавать функции, которые принимают переменное число аргументов. Функция format
, найденная в библиотеке base2 Дином Эдвардсом, демонстрирует эту гибкость:
function format(string) { var args = arguments; var pattern = new RegExp("%([1-" + arguments.length + "])", "g"); return String(string).replace(pattern, function(match, index) { return args[index]; }); };
Вы предоставляете строку шаблона, в которую вы добавляете заполнители для значений, используя %1
— %9
, а затем предоставляете до 9 других аргументов, которые представляют строки для вставки. Например:
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");
Приведенный выше код вернет строку "And the papers want to know whose shirt you wear"
.
Вы могли заметить, что в определении функции для format
мы указали только один аргумент: string
. JavaScript позволяет нам передавать функции любое количество аргументов независимо от определения функции, а объект arguments
имеет доступ ко всем из них.
Преобразовать его в реальный массив
Несмотря на то, что arguments
не является реальным массивом JavaScript, мы можем легко преобразовать его в один с помощью стандартного метода Array
, slice
, например:
var args = Array.prototype.slice.call(arguments);
Переменная args
теперь будет содержать правильный объект Array
JavaScript, содержащий все значения из объекта arguments
.
Создание функций с предустановленными аргументами
Объект arguments
позволяет нам выполнять всевозможные трюки JavaScript. Вот определение для функции makeFunc
. Эта функция позволяет вам предоставить ссылку на функцию и любое количество аргументов для этой функции. Он возвратит анонимную функцию, которая вызывает указанную вами функцию, и предоставляет предварительно заданные аргументы вместе с любыми новыми аргументами, предоставляемыми при вызове анонимной функции:
function makeFunc() { var args = Array.prototype.slice.call(arguments); var func = args.shift(); return function() { return func.apply(null, args.concat(Array.prototype.slice.call(arguments))); }; }
Первый аргумент, предоставленный makeFunc
, считается ссылкой на функцию, которую вы хотите вызвать (да, в этом простом примере проверка ошибок отсутствует), и он удаляется из массива arguments. makeFunc
возвращает анонимную функцию, которая использует метод apply
объекта Function
для вызова указанной функции.
Первый аргумент для apply
относится к области, в которой будет вызываться функция; в основном к какому ключевому слову this
будет относиться внутри вызываемой функции. Пока это немного продвинуто, поэтому мы просто держим это значение null
. Второй аргумент — это массив значений, которые будут преобразованы в объект arguments
для функции. makeFunc
объединяет исходный массив значений в массив аргументов, предоставленных анонимной функции, и передает их вызываемой функции.
Допустим, вам нужно было вывести сообщение, в котором шаблон всегда был одинаковым. Чтобы избавить вас от необходимости makeFunc
в кавычки шаблон каждый раз, когда вы makeFunc
функцию format
вы можете использовать служебную функцию makeFunc
чтобы вернуть функцию, которая будет вызывать format
для вас, и автоматически заполнить аргумент шаблона:
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
Вы можете вызывать функцию majorTom
несколько раз так:
majorTom("stepping through the door"); majorTom("floating in a most peculiar way");
Каждый раз, когда вы вызываете функцию majorTom
она вызывает функцию format
с уже заполненным первым аргументом — шаблоном. Вышеуказанные вызовы возвращают:
"This is Major Tom to ground control. I'm stepping through the door." "This is Major Tom to ground control. I'm floating in a most peculiar way."
Создайте самоссылающиеся функции
Вы можете подумать, что это круто, но подождите, у аргументов есть еще один сюрприз; у него есть еще одно полезное свойство: callee
. arguments.callee
содержит ссылку на функцию, которая создала объект arguments
. Как мы можем использовать такую вещь? arguments.callee
— удобный способ, которым анонимная функция может ссылаться на себя.
repeat
- это функция, которая принимает ссылку на функцию и 2 числа. Первое число - это количество вызовов функции, а второе - задержка в миллисекундах между каждым вызовом. Вот определение дляrepeat
:function repeat(fn, times, delay) { return function() { if(times-- > 0) { fn.apply(null, arguments); var args = Array.prototype.slice.call(arguments); var self = arguments.callee; setTimeout(function(){self.apply(null,args)}, delay); } }; }
repeat
используетarguments.callee
для получения ссылки в переменнойself
на анонимную функцию, которая запускает изначально предоставленную функцию. Таким образом, анонимная функция может вызывать себя снова после задержки, используя стандартную функциюsetTimeout
.Итак, у меня есть эта, по общему признанию упрощенная, функция в моем приложении, которая берет строку и выскакивает окно с предупреждением, содержащим эту строку:
function comms(s) { alert(s); }
Тем не менее, я хочу создать специальную версию этой функции, которая повторяется 3 раза с задержкой в 2 секунды между каждым разом. С моей функцией
repeat
я могу сделать это:var somethingWrong = repeat(comms, 3, 2000); somethingWrong("Can you hear me, major tom?");
Результатом вызова
somethingWrong
является окно предупреждения, повторяемое 3 раза с задержкой в 2 секунды между каждым предупреждением.
arguments
не часто используются, немного причудливы, но полны неожиданностей и их стоит узнать!