8.1. Определение функций
Определение функций выполняется с помощью ключевого слова
<b>function</b>
, которое может использоваться в выражениях определения функций (раздел 4.3) или в инструкциях объявления функций (раздел 5.3.2). В любом случае определение функции начинается с ключевого слова
<b>function</b>
, за которым указываются следующие компоненты:
• Идентификатор, определяющий имя функции. Имя является обязательной частью инструкции объявления функции: оно будет использовано для создания новой переменной, которой будет присвоен объект новой функции. В выражениях определения функций имя может отсутствовать: при его наличии имя будет ссылаться на объект функции только в теле самой функции.
• Пара круглых скобок вокруг списка из нуля или более идентификаторов, разделенных запятыми. Эти идентификаторы будут определять имена параметров функции и в теле функции могут использоваться как локальные переменные.
• Пара фигурных скобок с нулем или более инструкций JavaScript внутри. Эти инструкции составляют тело функции: они выполняются при каждом вызове функции.
В примере 8.1 показано несколько определений функций в виде инструкций и выражений. Обратите внимание, что определения функций в виде выражений удобно использовать, только если они являются частью более крупных выражений, таких как присваивание или вызов функции, которые выполняют некоторые действия с помощью вновь объявленной функции.
Именование функций
В качестве имени функции может использоваться любой допустимый идентификатор. Старайтесь выбирать функциям достаточно описательные, но не длинные имена. Искусство сохранения баланса между краткостью и информативностью приходит с опытом. Правильно подобранные имена функций могут существенно повысить удобочитаемость (а значит, и простоту сопровождения) ваших программ.
Чаще всего в качестве имен функций выбираются глаголы или фразы, начинающиеся с глаголов. По общепринятому соглашению имена функций начинаются со строчной буквы. Если имя состоит из нескольких слов, в соответствии с одним из соглашений они отделяются друг от друга символом подчеркивания, примерно так:
<b>like_this(),</b>
по другому соглашению все слова, кроме первого, начинаются с прописной буквы, примерно так:
<b>likeThis().</b>
Имена функций, которые, как предполагается, реализуют внутреннюю, скрытую от посторонних глаз функциональность, иногда начинаются с символа подчеркивания.
В некоторых стилях программирования или в четко определенных программных платформах бывает полезно давать наиболее часто используемым функциям очень короткие имена. Примером может служить библиотека
<b>jQuery</b>
клиентского JavaScript (описываемая в главе 19), в которой широко используется функция с именем
<b>$()</b>
(да-да, просто знак доллара). (В разделе 2.4 уже говорилось, что в идентификаторах JavaScript помимо алфавитно-цифровых символов допускается использовать знаки доллара и подчеркивания.)
*********************************************************
Пример 8.1. Определения JavaScript-функций
<b>// Выводит имена и значения всех свойств объекта о. Возвращает undefined,</b>
<b>function printprops(o) {</b>
<b> for(var p in o)</b>
<b> console.log(p + ": " + o[p] + "\n");</b>
<b>}</b>
<b>// Вычисляет Декартово расстояние между точками (х1,у1) и (х2,у2).</b>
<b>function distance(x1, у1. х2, у2) {</b>
<b> var dx = х2 - х1; var dy = у2 - у1; </b>
<b> return Math.sqrt(dx*dx + dy*dy);</b>
<b>}</b>
<b>// Рекурсивная функция (вызывающая сама себя), вычисляющая факториал</b>
<b>// Напомню, что х! - это произведение х и всех положительных целых чисел, меньше X.</b>
<b>function factorial(x) {</b>
<b> if (х <= 1) return 1;</b>
<b> return x * factorial(x-1);</b>
<b>}</b>
<b>// Следующее выражение определяет функцию, вычисляющую квадрат аргумента.</b>
<b>// Обратите внимание, что она присваивается переменной</b>
<b>var square = function(x) { return x*x; }</b>
<b>// Выражения определения функций могут иметь имена, что позволяет</b>
<b>// производить рекурсивные вызовы.</b>
<b>var f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); };</b>
<b>// Выражения определения функций могут также использоваться в качестве</b>
<b>// аргументов других выражений:</b>
<b>data.sort(function(a,b) { return a-b: }):</b>
<b>// Выражения определения функций иногда могут тут же вызываться: </b>
<b>var tensquared = (function(x) {return x*x;}(10));</b>
Обратите внимание, что в выражениях определения функций имя функции может отсутствовать. Инструкция объявления функции фактически объявляет переменную и присваивает ей объект функции. Выражение определения функции, напротив, не объявляет переменную. Однако в выражениях определения допускается указывать имя функции, как в функции вычисления факториала выше, которое может потребоваться в теле функции для вызова себя самой. Если выражение определения функции включает имя, данное имя будет ссылаться на объект функции в области видимости этой функции. Фактически имя функции становится локальной переменной, доступной только в теле функции. В большинстве случаев имя функции не требуется указывать в выражениях определения, что делает определения более компактными. Особенно удобно использовать выражения для определения однократно используемых функций, как в последних двух примерах выше.
Как описывалось в разделе 5.3.2, инструкции объявления функций «поднимаются» в начало сценария или вмещающей их функции, благодаря чему объявленные таким способом функции могут вызываться в программном коде выше объявления. Это не относится к функциям, которые определяются в виде выражений: чтобы вызвать функцию, необходимо иметь возможность сослаться на нее, однако нельзя сослаться на функцию, которая определяется с помощью выражения, пока она не будет присвоена переменной. Объявления переменных также поднимаются вверх (раздел 3.10.1), но операции присваивания значений этим переменным не поднимаются, поэтому функции, определяемые в виде выражений, не могут вызываться до того, как они будут определены.