Статьи

аргументы: странность JavaScript

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 не часто используются, немного причудливы, но полны неожиданностей и их стоит узнать!