Functionsbeginner
Function Hoisting and Declaration vs Expression
How function declarations, function expressions, and named function expressions differ in hoisting behavior and use cases.
Three ways to define a function, and they differ in when the name is usable.
A function declaration is like a fully-built house that's already standing when you arrive, ready to walk into. A function expression is like an empty lot with a sign showing whose house will eventually be built there — the sign (variable name) exists early, but you can't move in (call it) until construction (the assignment) actually finishes.
Key Concepts
1
function declared() {} // declaration
const expr = function () {}; // expression
const named = function inner() {}; // named expression
const arrow = () => {}; // arrow expression2
Only the declaration is available before its line.
declared(); // works
expr(); // TypeError: expr is not a function
arrow(); // ReferenceError -- TDZ3
function declared() {}
var expr = function () {};
const arrow = () => {};4
The declaration is hoisted whole. An expression follows its variable's rules, so var gives undefined and
const throws.
varundefinedconst
5
The named function expression has a use. The inner name is visible only inside the function:
6
const fact = function f(n) {
return n <= 1 ? 1 : n * f(n - 1); // f, not fact
};7
f; // ReferenceError outside8
That matters because fact could be reassigned, and the recursion would break. Referring to the inner name
is safe. It also gives the function a proper name in stack traces, which anonymous expressions do not.
fact
9
Declarations inside blocks are the edge case.
if (true) {
function g() {}
}
g(); // works in modern strict mode? depends10
Behaviour has differed between engines and between strict and sloppy mode. Declare functions at the top
level of a scope, or use an expression — the ambiguity is not worth navigating.
11
Which to use.
a top-level utility declaration -- hoisting is harmless
and the name appears in traces
a callback or a value arrow
a method on an object the method shorthand
recursive, assigned to a
variable named expression12
The practical point. Hoisting lets you call a declared function before defining it, and doing so
deliberately makes code harder to follow.
13
Its real value is that a file of helper functions does not need to be ordered by dependency — which is a
convenience, not a technique.
14
What the interviewer is probing.1. "Which can you call before its line?" Probing: the difference. Stalls: "Both." *Moves
up:* a declaration, which is fully hoisted; an expression assigned to a variable is not and throws
TypeError.
15
2. "Are function declarations hoisted out of blocks?" Probing: the messy corner. Stalls:
"Yes, like var." Moves up: in strict mode and modules they are block-scoped; the legacy
sloppy-mode behaviour differed between engines, which is why it is avoided.
16
3. "Why prefer const with an arrow function?" Probing: the argument. Stalls: "Style." *Moves
up:* it cannot be reassigned or used before definition, so the temporal dead zone turns an ordering
mistake into an immediate error.
17
4. "What is a named function expression for?" Probing: the small benefit. Stalls: "Nothing."
Moves up: the name is visible inside for recursion and appears in stack traces, without leaking
into the enclosing scope.