Function Declaration vs Function Expression in JavaScript

Introduction
If you've been writing JavaScript for a while, you've probably used both without thinking much about which one you're reaching for. They look similar, and for basic cases, they behave similarly too. But they're not the same thing, and the difference actually matters once your code grows past a few lines.
What a Function Is (And Why It Exists)
A function is a block of code you can name and reuse. Without functions, you'd write the same logic everywhere it's needed. With functions, you write it once and call it whenever.
That's it. No mystery. Here's the clearest example:
// Without a function
let result1 = 5 + 3;
let result2 = 10 + 3;
let result3 = 7 + 3;
// With a function
function addThree(num) {
return num + 3;
}
let result1 = addThree(5);
let result2 = addThree(10);
let result3 = addThree(7);
If the logic changes later, you fix it in one place instead of hunting through every file.
Function Declaration
A function declaration is what most people learn first. You write the function keyword, give it a name, and define the body.
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
Clean and readable. The function has a name (add), takes two parameters, and returns their sum.
Function Expression
A function expression is when you assign a function to a variable.
const add = function(a, b) {
return a + b;
};
console.log(add(2, 3)); // 5
Same behavior here. You're still calling add(2, 3) and getting 5. The difference is in how the function was created, not what it does.
You can also use arrow function syntax, which is just a shorter way to write a function expression:
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
Arrow functions are common in modern JavaScript. They're still function expressions, just written more compactly.
The Big Difference: Hoisting
This is where things actually diverge.
JavaScript does something called hoisting before running your code. It scans the file and moves certain declarations to the top. Function declarations get fully hoisted, meaning the browser knows about the entire function before any code runs.
So this works:
console.log(add(2, 3)); // 5 -- called before the function is defined
function add(a, b) {
return a + b;
}
You called add before it was written in the file, and JavaScript didn't complain. That's hoisting in action.
Now try the same thing with a function expression:
console.log(add(2, 3)); // Error: Cannot access 'add' before initialization
const add = function(a, b) {
return a + b;
};
This throws an error. The variable add is hoisted (JavaScript knows it exists), but its value isn't assigned yet when you try to call it. You have to define it before using it.
The short version: declarations are available anywhere in their scope, expressions are only available after the line where they're defined.
Key Differences at a Glance
| Point | Function Declaration | Function Expression |
|---|---|---|
| Syntax | function name() {} |
const name = function() {} |
| Hoisted | Yes (fully) | No (only the variable) |
| Can call before definition | Yes | No |
| Named | Always | Optional |
When to Use Each
Use a function declaration when you're writing utility functions or anything that should be available throughout a file. The hoisting behavior means you can organize your file however reads best, putting helper functions at the bottom even if the main logic uses them higher up.
// This is fine -- greet is hoisted
greet("Sam");
function greet(name) {
console.log("Hello, " + name);
}
Use a function expression when you need to assign a function dynamically, pass it as an argument, or return it from another function. Expressions treat functions as values, which is what makes callbacks and higher-order functions work.
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(function(n) {
return n * 2;
});
// Or with arrow syntax
const doubled = numbers.map(n => n * 2);
You'd never write a function declaration inline like that. Expressions fit naturally wherever a value would go.
Arrow functions specifically are worth using when you don't need your own this context (they inherit this from the surrounding scope). For callbacks, array methods, and short transformations, they're the go-to.
A Practical Rule of Thumb
If you're defining a standalone, named function that you'll reuse across your file, go with a declaration. If you're passing a function somewhere, storing it in a variable, or building it conditionally, go with an expression.
Neither is universally better. The right choice comes down to what your code is doing and what makes the intent clear to whoever reads it next.




