Функциональные выражения в JavaScript
JavaScript предлагает несколько способов определения функций: объявления функций и функциональные выражения — ключевые концепции для разработчиков.
Введение в функциональные выражения в JavaScript
JavaScript предлагает несколько способов определить функции, и два из наиболее фундаментальных — это объявления функций и функциональные выражения. Функциональное выражение позволяет обращаться с функцией как с любым другим значением: можно сохранить её в переменную, передать в другую функцию или вернуть из неё. Понимание того, чем выражения отличаются от объявлений — особенно в части всплытия — поможет избежать целого класса запутанных ошибок.
На этой странице рассматриваются синтаксис функциональных выражений, причины их отличия от объявлений, именованные выражения, наиболее распространённые практические применения (коллбэки, IIFE, обработчики событий, асинхронный код), а также связь всего этого с современными стрелочными функциями.
Функциональные выражения: синтаксис и использование
Что такое функциональное выражение?
Функциональное выражение определяет функцию как часть более крупного выражения — как правило, в правой части присваивания. Сама функция является просто значением, а переменная, которой она присвоена, становится способом её вызова. Вот наиболее базовая форма:
Сравните это с объявлением функции, которое начинается с ключевого слова function как самостоятельного оператора:
Оба варианта создают вызываемую функцию greet, однако движок обрабатывает их в разное время — именно об этом следующий раздел.
Всплытие: ключевое отличие
Объявления функций всплывают: движок читает их на этапе компиляции, поэтому функция существует до той строки, где она написана. Её можно вызвать раньше в файле. Функциональные выражения так не работают — значение функции присваивается только тогда, когда выполнение достигает этой строки, поэтому слишком ранний вызов завершится ошибкой:
Примечание: При использовании var имя greet всплывает, но его значение равно undefined до момента присваивания, поэтому ранний вызов выбрасывает TypeError ("greet is not a function"). При использовании let или const имя находится во временной мёртвой зоне, и вы получите ReferenceError. В любом случае правило одинаково: определяйте функциональное выражение до его использования.
Характеристики функциональных выражений
- Анонимные функции: функциональные выражения нередко бывают анонимными — у функции нет собственного имени, и к ней обращаются через переменную.
- Хранение в переменных: функция является значением, поэтому она хранится в переменной (или в элементе array, свойстве object и т. д.).
- Объекты первого класса: в JavaScript функции являются объектами первого класса — их можно передавать в качестве аргументов, возвращать из других функций и присваивать переменным.
- Именованные функциональные выражения: выражение может иметь собственное имя (например,
let fn = function myFunc() {}). Имя видно только внутри функции, что улучшает трассировку стека и позволяет функции вызывать саму себя. - Стрелочные функции: в современном коде часто используются стрелочные функции (
() => {}) как более краткая форма выражения, хотя они иначе обрабатываютthis.
Именованные функциональные выражения
Присвоение выражению внутреннего имени позволяет функции надёжно ссылаться на саму себя — удобно для рекурсии — даже если внешняя переменная впоследствии будет переназначена:
Практическое применение функциональных выражений
Функции обратного вызова
Наиболее распространённое применение функционального выражения — это коллбэк: функция, передаваемая в другую функцию и выполняемая позже, после завершения какой-либо операции. Передача функции прямо на месте в виде выражения сохраняет логику там, где она используется:
IIFE (немедленно вызываемое функциональное выражение)
IIFE — это функциональное выражение, которое выполняется сразу в момент определения. Обёртывающие скобки превращают функцию в выражение, а завершающие () вызывают её немедленно. Это был классический способ создать приватную область видимости и предотвратить утечку переменных в глобальную область:
Примечание: Сегодня блочные let/const и ES-модули покрывают большую часть задач, для которых использовались IIFE, поэтому в новом коде они встречаются реже — однако по-прежнему широко применяются в старых библиотеках и бандлированных скриптах.
Функциональные выражения vs объявления функций
| Объявление функции | Функциональное выражение | |
|---|---|---|
| Синтаксис | function f() {} как самостоятельный оператор | let f = function () {} внутри выражения |
| Всплытие | Полностью всплывает — можно вызывать до строки объявления | Недоступна до выполнения присваивания |
| Имя | Всегда именованная | Часто анонимная (может иметь имя) |
| Лучше подходит для | Вспомогательных функций верхнего уровня, используемых во всём файле | Коллбэков, IIFE, условных определений |
Практическое правило: используйте объявление для отдельной многократно используемой функции, а выражение — когда функция является значением, которое нужно куда-то передать или определить условно.
Расширенные примеры и сценарии использования
Обработка событий
В браузере функциональные выражения — естественный способ добавления обработчиков событий, поскольку функция передаётся напрямую в addEventListener:
document.getElementById('myButton').addEventListener('click', function () {
console.log('Button clicked!');
});Асинхронное программирование
При работе с Promise и async/await функциональные выражения предоставляют лаконичный способ передавать блоки кода. Здесь функциональное выражение обрабатывает каждое успешно разрешённое значение:
Заключение
Освоение функциональных выражений в JavaScript является ключом к написанию эффективного и поддерживаемого кода. Их гибкость в сочетании с возможностями функционального программирования в JavaScript делает их незаменимым инструментом в арсенале разработчика.
Помните, что выбор между функциональным выражением и объявлением функции зависит от конкретных требований вашего кода и контекста, в котором вы работаете. Продолжайте практиковаться и исследовать эти концепции, чтобы углубить понимание и уверенно работать с JavaScript.