Are function declarations hoisted?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Yes — and they are the only thing hoisted completely. A function declaration has both its name and its body available before the first line runs, so calling it earlier in the scope works:
greet(); // "hello"
function greet() {
console.log("hello");
}
Function expressions and arrow functions are not functions as far as hoisting is concerned — they are variables that happen to hold a function, so they follow the rules of var, let or const:
speak(); // TypeError: speak is not a function
var speak = function () {}; // `speak` exists but is `undefined`
shout(); // ReferenceError: Cannot access 'shout'
const shout = () => {}; // temporal dead zone
Notice the two errors differ, and the difference tells you which form was used. TypeError means the variable exists and holds undefined; ReferenceError means you are inside the TDZ of a let/const.
Details worth knowing
Declarations are scoped to the enclosing function or block, not the whole file:
function outer() {
inner(); // works, hoisted within outer
function inner() {}
}
inner(); // ReferenceError — not visible here
If the same name is declared twice, the later declaration wins, because both are processed before execution:
fn(); // "second"
function fn() { console.log("first"); }
function fn() { console.log("second"); }
Function declarations inside blocks (if, for) behave inconsistently between strict and sloppy mode. If you need a function inside a block, assign a function expression to a const instead.
