Function Declaration vs Function Expression: What's the Difference?
Also onpreet-jain.hashnode.dev/function-declaration-vs-function-expressionCode repetition is the enemy. You write the same logic in ten places, then you need to change it, and now you're hunting through every file. Functions solve this — they're named blocks of code you can reuse by calling them whenever you need.
function greet(name) {
return 'Hello, ' + name;
}
console.log(greet('Alice')); // 'Hello, Alice'
console.log(greet('Bob')); // 'Hello, Bob'One definition, unlimited use. But JavaScript gives you two ways to write functions, and they're not quite the same.
Function Declaration
A function declaration defines a named function:
function add(a, b) {
return a + b;
}This creates a function called add that takes two parameters and returns their sum. You can call it anywhere in your code after this definition appears.
Function Expression
A function expression assigns a function to a variable:
const add = function(a, b) {
return a + b;
};The function here is anonymous — it has no name. It gets assigned to the variable add, and you call it using that variable.
You can also name function expressions if you want:
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1);
};The name fact is only available inside the function itself — useful for recursive calls.
Side-by-Side Comparison
| Aspect | Declaration | Expression |
|---|---|---|
| Syntax | function name() | const name = function() |
| Named or anonymous | Always named | Can be either |
| Hoisting | Fully hoisted | Variable hoisted, not value |
| Where in code | Anywhere in scope | Must be defined before use |
The biggest practical difference comes down to hoisting.
Hoisting: Why It Matters
JavaScript processes your code before running it. During this preparation phase, it "hoists" — pulls to the top — function declarations and variable declarations. But there's a catch with function expressions.
console.log(add(2, 3)); // 5 — works!
function add(a, b) {
return a + b;
}Function declarations are hoisted entirely. You can call them before they appear in your code because the entire function gets moved to the top of scope during processing.
Now try the same with a function expression:
console.log(multiply(2, 3)); // TypeError: multiply is not a function
const multiply = function(a, b) {
return a * b;
};This fails. The variable multiply is hoisted (so you don't get a ReferenceError), but it's undefined until the assignment runs. Calling undefined() throws a TypeError.
The fix is straightforward: define your function expressions before you call them.
const multiply = function(a, b) {
return a * b;
};
console.log(multiply(2, 3)); // 6 — now it worksWhen to Use Each
Use declarations when:
You need the function available anywhere in the scope
The function is self-contained and doesn't depend on external state
You want maximum flexibility with call order
Use expressions when:
You're assigning functions to variables or properties
You're passing functions as arguments to other functions
You need anonymous functions for one-off use (callbacks, array methods)
// Function expression passed as a callback
setTimeout(function() {
console.log('This runs after 1 second');
}, 1000);
// Function expression with array method
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function(n) {
return n * 2;
});Modern JavaScript has arrow functions, which are a compact form of function expressions:
const doubled = numbers.map(n => n * 2);Arrow functions are worth learning separately, but under the hood they're still expressions.
Practice Assignment
Try these exercises to reinforce the concepts:
Write a function declaration that multiplies two numbers
Write the same logic as a function expression
Call both functions and print the results
// Declaration
function multiply(a, b) {
return a * b;
}
// Expression
const multiply = function(a, b) {
return a * b;
};
console.log(multiply(3, 4)); // 12
console.log(multiply(5, 6)); // 30Now test hoisting. Try calling multiply before the expression definition and after:
// Before definition — fails
try {
console.log(multiply(2, 2)); // TypeError
} catch (e) {
console.log('Failed before definition');
}
// Expression defined here
const multiply = function(a, b) {
return a * b;
};
// After definition — works
console.log(multiply(2, 2)); // 4Wrapping Up
The difference comes down to hoisting and syntax. Function declarations are fully hoisted and always named. Function expressions are assigned to variables, can be anonymous, and require the variable to be defined before use.
For most code, either works. The choice becomes meaningful when you're passing functions around (callbacks, array methods) or need to be precise about when a function is available. Get comfortable with both forms — you'll see both in real codebases.