В JavaScript функция является значением, таким же как строка или число.
Как и любое значение, объявленную функцию можно вывести, вот так:
Обратим внимание на то, что в последней строке после sayHi
нет скобок. То есть, функция не вызывается, а просто выводится на экран.
Функцию можно скопировать в другую переменную:
(1)
как бы говорит интерпретатору "создай функцию и помести её в переменную sayHi
(2)
мы копируем функцию в новую переменную func
. Ещё раз обратите внимание: после sayHi
нет скобок. Если бы они были, то вызов var func = sayHi()
записал бы в func
результат работы sayHi()
(кстати, чему он равен? правильно, undefined
, ведь внутри sayHi
нет return
).(3)
функцию можно вызывать и как sayHi()
и как func()
(4)
выдаст ошибку.Обычные значения, такие как числа или строки, представляют собой данные. А функцию можно воспринимать как действие.
Это действие можно запустить через скобки ()
, а можно и скопировать в другую переменную, как было продемонстрировано выше.
Существует альтернативный синтаксис для объявления функции, который ещё более наглядно показывает, что функция – это всего лишь разновидность значения переменной.
Он называется «Function Expression» (функциональное выражение) и выглядит так:
Например:
«Классическое» объявление функции, о котором мы говорили до этого, вида function имя(параметры) {...}
, называется в спецификации языка «Function Declaration».
Несмотря на немного разный вид, по сути две эти записи делают одно и то же:
Оба этих объявления говорят интерпретатору: "объяви переменную sum
, создай функцию с указанными параметрами и кодом и сохрани её в sum
".
Основное отличие между ними: функции, объявленные как Function Declaration, создаются интерпретатором до выполнения кода.
Поэтому их можно вызвать до объявления, например:
А если бы это было объявление Function Expression, то такой вызов бы не сработал:
Это из-за того, что JavaScript перед запуском кода ищет в нём Function Declaration (их легко найти: они не являются частью выражений и начинаются со слова function
) и обрабатывает их.
А Function Expression создаются в процессе выполнения выражения, в котором созданы, в данном случае – функция будет создана при операции присваивания sayHi = function...
Как правило, возможность Function Declaration вызвать функцию до объявления – это удобно, так как даёт больше свободы в том, как организовать свой код.
Можно расположить функции внизу, а их вызов – сверху или наоборот.
В некоторых случаях «дополнительное удобство» Function Declaration может сослужить плохую службу.
Например, попробуем, в зависимости от условия, объявить функцию sayHi
по-разному:
Function Declaration при use strict
видны только внутри блока, в котором объявлены. Так как код в учебнике выполняется в режиме use strict
, то будет ошибка.
А что, если использовать Function Expression?
Или даже так:
Оба этих варианта работают правильно, поскольку, в зависимости от условия, создаётся именно та функция, которая нужна.
Взглянем ещё на один пример – функцию ask(question, yes, no)
с тремя параметрами:
question
yes
no
Она выводит вопрос на подтверждение question
и, в зависимости от согласия пользователя, вызывает функцию yes()
или no()
:
Какой-то очень простой код, не правда ли? Зачем, вообще, может понадобиться такая ask
?
…Оказывается, при работе со страницей такие функции как раз очень востребованы, только вот спрашивают они не простым confirm
, а выводят более красивое окно с вопросом и могут интеллектуально обработать ввод посетителя. Но это всё потом, когда перейдём к работе с интерфейсом.
Здесь же обратим внимание на то, что то же самое можно написать более коротко:
Здесь функции объявлены прямо внутри вызова ask(...)
, даже без присвоения им имени.
Функциональное выражение, которое не записывается в переменную, называют анонимной функцией.
Действительно, зачем нам записывать функцию в переменную, если мы не собираемся вызывать её ещё раз? Можно просто объявить непосредственно там, где функция нужна.
Такого рода код возникает естественно, он соответствует «духу» JavaScript.
Существует ещё один способ создания функции, который используется очень редко, но упомянем и его для полноты картины.
Он позволяет создавать функцию полностью «на лету» из строки, вот так:
То есть, функция создаётся вызовом new Function(params, code)
:
params
code
Таким образом можно конструировать функцию, код которой неизвестен на момент написания программы, но строка с ним генерируется или подгружается динамически во время её выполнения.
Пример использования – динамическая компиляция шаблонов на JavaScript, мы встретимся с ней позже, при работе с интерфейсами.
Функции в JavaScript являются значениями. Их можно присваивать, передавать, создавать в любом месте кода.
Между этими двумя основными способами создания функций есть следующие различия:
Function Declaration | Function Expression | |
---|---|---|
Время создания | До выполнения первой строчки кода. | Когда управление достигает строки с функцией. |
Можно вызвать до объявления | Да (т.к. создаётся заранее) |
Нет |
Условное объявление в if |
Не работает |
Работает |
Иногда в коде начинающих разработчиков можно увидеть много Function Expression. Почему-то, видимо, не очень понимая происходящее, функции решают создавать как var func = function()
, но в большинстве случаев обычное объявление функции – лучше.
Если нет явной причины использовать Function Expression – предпочитайте Function Declaration.
Сравните по читаемости:
Function Declaration короче и лучше читается. Дополнительный бонус – такие функции можно вызывать до того, как они объявлены.
Используйте Function Expression только там, где это действительно нужно и удобно.