Menu
Русский

Объявление функций в JavaScript: синтаксис и hoisting

Разбираемся, как объявлять функции в JavaScript: ключевое слово function, параметры, return, всплытие (hoisting) и когда выбрать declaration, а когда expression.

Функция — это именованный блок шагов

Когда нужно дать имя какому-то куску логики и переиспользовать его, вы пишете функцию. Самый старый и самый очевидный способ в JavaScript — это function declaration (объявление функции): ключевое слово function, а за ним имя.

index.js
Output
Click Run to see the output here.

Читаем слева направо:

  • function — ключевое слово, с которого начинается объявление функции.
  • greet — имя функции.
  • (name) — список параметров, то есть входные данные функции.
  • Блок в фигурных скобках — тело функции.
  • greet("Ada") — это вызов. JavaScript выполняет тело, подставив в name значение "Ada".

Само по себе объявление функции её не запускает. Запускает — вызов.

Параметры и аргументы

Параметр — это имя, указанное в определении функции. Аргумент — конкретное значение, которое вы передаёте при вызове. В обиходе эти слова используют как синонимы, но разница становится важна, когда начинаешь разбирать сообщения об ошибках.

index.js
Output
Click Run to see the output here.

Здесь base и exponent — это параметры, а 2 и 10 — аргументы. JavaScript связывает их по порядку: первый аргумент уходит в первый параметр, второй — во второй, и так далее.

В отличие от некоторых других языков, JavaScript не будет ругаться, если вы передадите не столько аргументов, сколько ожидается. Недостающие станут undefined, а лишние просто молча проигнорируются. С одной стороны, это гибко, с другой — иногда подставляет подножку. К значениям по умолчанию и rest-параметрам мы ещё вернёмся в следующих разделах.

return: возвращаем значение из функции

console.log просто печатает что-то в консоль. А вот return в javascript передаёт значение обратно тому, кто вызвал функцию, чтобы его можно было дальше использовать:

index.js
Output
Click Run to see the output here.

Без return функция вернёт undefined:

index.js
Output
Click Run to see the output here.

return также моментально завершает работу функции. Ранний выход через return — это стандартный приём, позволяющий отсечь крайние случаи до основной логики:

index.js
Output
Click Run to see the output here.

Ранний возврат (early return) спасает основное тело функции от превращения в «лесенку» из if/else.

Hoisting функций в JavaScript: вызываем раньше, чем объявили

Вот момент, который реально ставит в тупик тех, кто пришёл из других языков. Объявления функций (function declaration) подвергаются всплытию (hoisting) — JavaScript как бы поднимает их в начало области видимости ещё до того, как начнёт выполнять код. То есть функцию спокойно можно вызвать строкой выше, чем она объявлена:

index.js
Output
Click Run to see the output here.

Этот код отработает без ошибок. Перед выполнением движок сканирует область видимости, регистрирует square как функцию, и только потом начинает построчно выполнять инструкции.

Это реальное различие в поведении между function declaration и остальными способами создать функцию (function expression, стрелочные функции). Последние всплывают как переменные — имя уже известно, но значение присваивается только тогда, когда исполнение дойдёт до нужной строки. Подробнее об этом — дальше.

Большинство стайл-гайдов всё равно советуют объявлять функции до того, как вы их вызываете. Hoisting — это подстраховка, а не приём, на который стоит опираться.

Разница между function declaration и function expression

Function declaration — это самостоятельная инструкция. Function expression появляется там, где ожидается значение — чаще всего после знака присваивания:

index.js
Output
Click Run to see the output here.

И объявление, и выражение дают вам вызываемую функцию. Но отличия всё же есть:

  • Function declaration всплывает целиком (полный hoisting). А function expression подчиняется правилам всплытия той переменной, которой она присвоена: const и let до момента выполнения строки находятся во временной мёртвой зоне (TDZ).
  • У declaration обязательно должно быть имя. Expression может быть анонимной, хотя именованная функция даёт более понятный стек вызовов при отладке.
  • Declaration нельзя писать где попало. В strict mode конструкция вида function foo() {} внутри блока if ведёт себя по-разному в разных движках — в таких местах лучше использовать expression.

Для большинства вспомогательных функций верхнего уровня в файле declaration смотрится естественнее. А вот когда функцию передают аргументом или присваивают свойству объекта, обычно берут function expression (или стрелочную функцию).

Имена и стиль оформления

Имя функции — это обещание того, что она делает. Несколько лишних символов на понятное, говорящее имя окупаются в первый же раз, когда код будет читать другой человек (или вы сами через полгода).

index.js
Output
Click Run to see the output here.

Пара соглашений, которых стоит придерживаться:

  • Имена функций — это глаголы: fetchProfile, computeTotal, sendEmail.
  • Пишем в camelCase — это норма в JavaScript.
  • Функции, возвращающие булево значение, часто начинаются с is, has или can: isValid, hasAccess, canEdit.

Суть в том, чтобы вызов функции читался как обычное предложение.

Небольшой рабочий пример

Соберём всё вместе — параметры, ранний return и говорящее имя:

index.js
Output
Click Run to see the output here.

Одно объявление, ранний выход через guard clause, понятный return. Этой схемы хватит для большинства функций, которые вы будете писать.

Дальше: стрелочные функции

Function declaration — рабочая лошадка, но современный JavaScript всё чаще тяготеет к более краткому синтаксису — стрелочным функциям. Особенно это заметно в колбэках и однострочниках. Выглядят они иначе, ведут себя иначе в отношении this — как раз об этом следующая страница.

Часто задаваемые вопросы

Как объявить функцию в JavaScript?

Пишем ключевое слово function, затем имя, круглые скобки с параметрами и тело в фигурных скобках. Например: function greet(name) { return 'Привет, ' + name; }. Вызывается такая функция по имени со скобками: greet('Ada').

Что такое hoisting (всплытие) функций в JavaScript?

Объявления функций поднимаются наверх своей области видимости ещё до выполнения кода — поэтому вызвать функцию можно даже выше той строки, где она написана. Но работает это только для function-объявлений: функциональные выражения и стрелочные функции, присвоенные let или const, так не всплывают.

В чём разница между function declaration и function expression?

Declaration — это самостоятельная инструкция (function greet() {}), и она всплывает. Expression — это присваивание функции переменной (const greet = function() {}), и тут действуют обычные правила hoisting для переменных. При этом declaration всегда имеет имя, а expression чаще всего анонимное.

Учитесь программировать с Coddy

НАЧАТЬ