Что знаешь о различии между function expression и function declaration
Function Declaration (объявление функции) и Function Expression (функциональное выражение) — это два основных способа определения функций в JavaScript. Главное различие между ними заключается в механизме поднятия (hoisting): объявления функций поднимаются вверх своей области видимости и доступны до выполнения кода, тогда как функциональные выражения доступны только после того, как интерпретатор дойдёт до их строки. Это влияет на то, когда и как можно использовать функции в коде.
Как это работает
Function Declaration
Function Declaration — это способ объявления функции с использованием ключевого слова function, за которым следует имя функции. Пример:
function sum(a, b) {
return a + b;
}Особенности:
- Поднятие (hoisting): объявление функции полностью поднимается вверх своей области видимости. Это означает, что функцию можно вызвать до её объявления в коде. Например, следующий код работает без ошибок:
console.log(sum(2, 3)); // 5
function sum(a, b) {
return a + b;
}-
Область видимости: функция доступна в пределах блока, в котором она объявлена. В строгом режиме (
'use strict') блочная область видимости ограничивает видимость функции внутри блока{}. -
Имя функции: имя является неизменным и не может быть переназначено. Попытка присвоить другое значение имени функции приведёт к ошибке в строгом режиме или будет проигнорирована в нестрогом.
Function Expression
Function Expression — это способ создания функции в рамках выражения. Функция присваивается переменной или передаётся как аргумент. Пример:
const sum = function(a, b) {
return a + b;
};Особенности:
- Поднятие: переменная, которой присвоена функция, поднимается, но её значение не инициализируется. Если используется
var, переменная будет иметь значениеundefinedдо строки присваивания, поэтому вызов функции до этого места приведёт к ошибкеTypeError. Если используетсяletилиconst, переменная попадает во временную мёртвую зону (temporal dead zone), и доступ к ней до объявления также вызовет ошибку.
console.log(sum(2, 3)); // TypeError: sum is not a function
var sum = function(a, b) {
return a + b;
};- Анонимные и именованные: функциональные выражения могут быть анонимными (без имени) или именованными. Именованные выражения полезны для отладки и рекурсии, так как имя доступно внутри самой функции.
const factorial = function fact(n) {
return n <= 1 ? 1 : n * fact(n - 1);
};- Использование в выражениях: функциональные выражения можно передавать как аргументы в другие функции, например, в
setTimeoutилиmap, что делает их удобными для колбэков.
Примеры использования
Рассмотрим практический пример, демонстрирующий разницу в поднятии:
// Function Declaration
console.log(declared()); // "declared"
function declared() {
return "declared";
}
// Function Expression
console.log(expression()); // ReferenceError: Cannot access 'expression' before initialization
const expression = function() {
return "expression";
};В первом случае функция declared вызывается до объявления, и это работает. Во втором случае expression объявлена через const, поэтому до строки инициализации она находится во временной мёртвой зоне, и обращение к ней вызывает ошибку.
Когда использовать
-
Function Declaration предпочтительнее, когда функция нужна в нескольких местах кода и её вызов может происходить до объявления. Это делает код более читаемым, так как функции можно размещать внизу модуля.
-
Function Expression используется, когда функция нужна как значение: для присваивания переменной, передачи в качестве аргумента или создания замыкания. Это даёт большую гибкость, например, можно переопределить функцию в зависимости от условий.
Подводные камни
-
Блочная область видимости: в строгом режиме Function Declaration внутри блока
{}видна только внутри этого блока. Это может привести к неожиданным ошибкам, если предполагать, что функция доступна снаружи. -
Временная мёртвая зона: при использовании
letилиconstдля функционального выражения, попытка вызвать функцию до объявления приведёт кReferenceError, а не кTypeError, как сvar. -
Именованные функциональные выражения: имя внутри функции доступно, но снаружи оно не видно. Это важно для рекурсии, но не для внешнего вызова.
Коротко
- Function Declaration поднимается полностью, Function Expression — нет.
- Function Declaration имеет неизменное имя, Function Expression может быть анонимным или именованным.
- Function Expression удобно использовать для колбэков и присваивания переменным.
- В строгом режиме Function Declaration ограничен блоком, а
let/constсоздают временную мёртвую зону для выражений.
Похожие вопросы
- Различие методов call apply bind20%
- Что такое макро и микро задачи20%
- В чем разница == и ===20%
- В чём разница между классической функцией и стрелочной20%
- С какими БД работал20%
- Какие способы изоляции стилей ты знаешь20%
- Какие были обязанности в прошлом проекте20%
- Какие будут первые действия если придешь на проект где нет предыдущего Backend-разработчика18%
