Function Statement vs Function Expression in JavaScript
January 4, 2026
Function Statement vs Function Expression in JavaScript
Overview
JavaScript provides two ways to define functions: Function Statements (declarations) and Function Expressions. They differ in hoisting behavior, when they can be called, and their use cases.
Function Statement (Declaration)
A function statement is hoisted to the top of its scope and can be called before it's declared.
Syntax
function functionName(parameters) {
// function body
}
Characteristics
// Can be called before declaration (hoisted)
greet("John"); // Works!
function greet(name) {
console.log("Hello", name);
}
// Function is hoisted, so this works:
console.log(typeof greet); // "function" (even before declaration in code)
Hoisting Behavior
// During hoisting, function declarations are moved to top
console.log(sayHello); // [Function: sayHello] (not undefined)
function sayHello() {
console.log("Hello");
}
// Equivalent to:
// function sayHello() { ... }
// console.log(sayHello);
Function Expression
A function expression assigns a function to a variable. It's not hoisted and cannot be called before declaration.
Syntax
const functionName = function(parameters) {
// function body
};
Characteristics
// Cannot be called before declaration
// sayHello("Jane"); // ReferenceError: Cannot access before initialization
const sayHello = function(name) {
console.log("Hi", name);
};
sayHello("Jane"); // Works after declaration
Hoisting Behavior
// Function expressions are not hoisted
console.log(sayHello); // undefined (not ReferenceError for var, but TDZ for let/const)
const sayHello = function() {
console.log("Hello");
};
Named Function Expression
A function expression can have a name, which is useful for debugging and recursion.
const calculate = function mathOperation(x, y) {
console.log("Calculating...");
// Name is only available inside the function
console.log(mathOperation.name); // "mathOperation"
return x + y;
};
console.log(calculate.name); // "mathOperation"
// console.log(mathOperation); // ReferenceError (not in outer scope)
Arrow Functions (Function Expression)
Arrow functions are a type of function expression with shorter syntax.
// Regular function expression
const add1 = function(a, b) {
return a + b;
};
// Arrow function expression
const add2 = (a, b) => {
return a + b;
};
// Arrow function (implicit return)
const add3 = (a, b) => a + b;
Key Differences
| Feature | Function Statement | Function Expression |
|---------|-------------------|---------------------|
| Hoisting | ✅ Hoisted | ❌ Not hoisted |
| Call before declaration | ✅ Yes | ❌ No |
| Syntax | function name() {} | const name = function() {} |
| Name | Required | Optional (can be anonymous) |
| this binding | Has own this | Has own this (arrow functions inherit) |
Use Cases
Function Statement
// Good for: Main functions, reusable utilities
function processData(data) {
// Can be called from anywhere in scope
return data.map(item => item * 2);
}
// Can call before declaration
const result = processData([1, 2, 3]);
Function Expression
// Good for: Callbacks, conditionally defined functions, closures
const button = document.getElementById("btn");
// Callback function
button.addEventListener("click", function() {
console.log("Button clicked");
});
// Conditional function
let greet;
if (user.isAdmin) {
greet = function() {
console.log("Hello Admin");
};
} else {
greet = function() {
console.log("Hello User");
};
}
// IIFE (Immediately Invoked Function Expression)
(function() {
console.log("IIFE executed");
})();
First-Class Functions
Both function statements and expressions are first-class citizens, meaning they can be:
- Assigned to variables
- Passed as arguments
- Returned from functions
// Function as argument
function processFunction(fn) {
console.log("Processing function...");
fn();
}
processFunction(function() {
console.log("I am a function passed as an argument");
});
// Function as return value
function createMultiplier(multiplier) {
return function(number) {
return number * multiplier;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 10
Common Patterns
Callback Pattern
// Function expression as callback
setTimeout(function() {
console.log("Delayed execution");
}, 1000);
// Arrow function as callback
setTimeout(() => {
console.log("Arrow function callback");
}, 1000);
Method Assignment
const obj = {
// Method (function expression in object)
greet: function(name) {
return `Hello, ${name}`;
},
// Shorthand method (ES6)
sayHello(name) {
return `Hi, ${name}`;
}
};
Best Practices
- Use function statements for main, reusable functions
- Use function expressions for callbacks and one-time use functions
- Use arrow functions when you need lexical
thisbinding - Be aware of hoisting - function statements can be called before declaration
Key Points
- Function Statement: Hoisted, can be called before declaration
- Function Expression: Not hoisted, must be declared before use
- Function expressions are more flexible (can be anonymous, conditional)
- Both are first-class functions (can be passed, returned, assigned)
- Arrow functions are a type of function expression
- Choose based on hoisting needs and use case