Question
I'm maintaining an existing JavaScript codebase and noticed that functions are defined in two different ways. I want to understand whether there is a meaningful difference between them, and when each style should be used.
The two patterns are:
var functionOne = function() {
// Some code
};
and:
function functionTwo() {
// Some code
}
What are the reasons for using these two different approaches? What are the advantages and disadvantages of each? Is there anything you can do with one that you cannot do with the other?
Short Answer
By the end of this page, you will understand the difference between function declarations and function expressions in JavaScript. You will learn how they behave with hoisting, where they are commonly used, how they affect readability and flexibility, and how to choose the right one in real code.
Concept
In JavaScript, both of these forms create functions, but they are not processed in exactly the same way.
function greet() {
console.log("Hello");
}
This is a function declaration.
var greet = function() {
console.log("Hello");
};
This is a function expression assigned to a variable.
Core difference
A function declaration defines a named function directly. A function expression creates a function as a value, then stores that value in a variable.
That matters because in JavaScript, functions are first-class values. This means a function can be:
- stored in a variable
- passed to another function
- returned from another function
- used as part of an object or array
Why the difference matters
The biggest practical difference is hoisting.
Function declaration hoisting
Function declarations are hoisted with their full definition, so they can be called before they appear in the code.
sayHi();
function sayHi() {
console.log("Hi");
}
This works.
Function expression hoisting
When a function is assigned to var, the variable declaration is hoisted, but the assignment is not.
sayHi();
var sayHi = function() {
console.log("Hi");
};
This does not work as expected. During hoisting, sayHi exists, but its value is initially undefined, so calling it causes an error.
Why developers choose one or the other
Function declarations are often used when:
- the function is a main part of the program logic
- you want readable top-level named functions
- you want to call the function before its definition appears
Function expressions are often used when:
- you want to pass a function around as a value
- you want to define a function conditionally or inside another expression
- you want a callback or inline function
- you want to attach behavior to variables, object properties, or module exports
Important note
In modern JavaScript, you will also often see:
const functionOne = function() {
// Some code
};
or:
const functionOne = () => {
// Some code
};
These are also function expressions, but using const is usually safer than var because it avoids some scope-related problems.
Mental Model
Think of a function declaration like a named tool that is placed in your toolbox before you start working.
A function expression is more like building a tool and then putting it into a labeled box.
- With a function declaration, JavaScript prepares the tool early, so you can use it anywhere in that scope.
- With a function expression, JavaScript first creates the box (
var functionOne), but the tool is not placed inside until execution reaches that line.
So:
- declaration = the tool is ready early
- expression = the label exists first, the tool arrives later
This mental model helps explain why one can be called before its definition and the other usually cannot.
Syntax and Examples
Function declaration
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
This creates a named function called add.
Function expression
var add = function(a, b) {
return a + b;
};
console.log(add(2, 3)); // 5
This creates a function and stores it in the variable add.
Named function expression
A function expression can also have its own internal name.
var factorial = function fact(n) {
if (n <= 1) {
return 1;
}
return n * fact(n - 1);
};
console.log(factorial(5)); // 120
Here:
factorialis the variable holding the functionfactis the function's internal name
This can be useful for recursion or debugging.
Passing a function as a value
Function expressions are commonly used inline.
setTimeout(function() {
console.log("Runs later");
}, 1000);
This is one reason function expressions are so common: JavaScript often treats functions as values.
Modern style note
In modern JavaScript, this is often written with const instead of var:
const add = function(a, b) {
return a + b;
};
This prevents accidentally reassigning the variable.
Step by Step Execution
Consider this example:
console.log(square(4));
function square(n) {
return n * n;
}
What happens
- JavaScript scans the scope.
- It finds the function declaration
square. - It hoists the full function definition.
console.log(square(4))runs.square(4)returns16.
Now compare that with:
console.log(square(4));
var square = function(n) {
return n * n;
};
What happens here
- JavaScript scans the scope.
- It finds
var squareand hoists only the variable declaration. - At this point,
squareisundefined. console.log(square(4))tries to callundefinedas a function.- JavaScript throws an error.
- The assignment to the function happens only when execution reaches that line.
Rough mental rewrite by the engine
This is not exactly how the engine works internally, but it is a useful model.
Function declaration
function square(n) {
return n * n;
}
console.log(square(4));
Function expression with var
var square;
console.log(square(4));
square = function(n) {
return n * n;
};
That simplified rewrite explains the different behavior.
Real World Use Cases
When function declarations are useful
1. Main reusable functions
If a function is an important part of the module, a declaration is often clear and readable.
function validateUser(user) {
return user && user.email;
}
2. Organizing helper functions
Some developers like putting high-level logic at the top and helper declarations below, relying on hoisting.
startApp();
function startApp() {
loadConfig();
}
function loadConfig() {
console.log("Loading config...");
}
When function expressions are useful
1. Callbacks
JavaScript APIs often expect functions as arguments.
[1, 2, 3].map(function(n) {
return n * 2;
});
2. Conditional assignment
You can choose a function at runtime.
var formatter;
if (isAdmin) {
formatter = function(name) {
return "Admin: " + name;
};
} else {
formatter = function(name) {
return name;
};
}
3. Object properties
Functions are often assigned as values inside objects.
const userService = {
getUser: function(id) {
return { id: id, name: "Sam" };
}
};
4. Event handlers
document.addEventListener("click", function() {
console.log("Clicked");
});
Real Codebase Usage
In real projects, both styles appear, but they are usually used with intent.
Common patterns
Top-level declarations for core logic
Developers often use function declarations for named operations that are central to a file.
function parseResponse(data) {
return JSON.parse(data);
}
function handleRequest(data) {
const result = parseResponse(data);
return result;
}
This makes stack traces readable and keeps main functions easy to find.
Function expressions for callbacks and local behavior
items.filter(function(item) {
return item.active;
});
This is common when the function is only needed in one place.
Guard clauses with named functions
Function declarations often pair well with readable validation flows.
function saveUser(user) {
if (!user) return;
if (!user.email) return;
console.log("Saving user");
}
Assigning behavior based on configuration
Function expressions work well when behavior depends on environment or options.
let log;
if (process.env.NODE_ENV === "production") {
log = function() {};
} else {
log = function(message) {
console.log(message);
};
}
Module and object composition
Functions are frequently assigned into objects, exports, and configuration structures.
const api = {
fetchUser: function(id) {
return `/users/${id}`;
}
};
Practical advice
In modern code:
- use function declarations for clear, reusable named functions
- use function expressions for inline callbacks and dynamic assignment
- prefer
constorletovervarfor function expressions
Common Mistakes
1. Calling a function expression before assignment
Broken code:
sayHello();
var sayHello = function() {
console.log("Hello");
};
Problem:
sayHello is undefined at the time of the call.
Fix:
var sayHello = function() {
console.log("Hello");
};
sayHello();
2. Assuming both forms hoist the same way
Many beginners think all functions can be called before they appear.
Broken assumption:
console.log(getTotal(2, 3));
var getTotal = function(a, b) {
return a + b;
};
Avoid this by remembering:
- function declarations hoist fully
varfunction expressions do not
3. Using var when reassignment is not needed
var multiply = function(a, b) {
return a * b;
};
This works, but const is often safer:
const multiply = function(a, b) {
return a * b;
};
4. Forgetting the semicolon after a function expression
Function declarations do not need a trailing semicolon, but variable assignments usually do.
Correct:
const greet = function() {
console.log("Hi");
};
5. Confusing anonymous and named functions
This is anonymous:
const greet = function() {
console.log("Hi");
};
This is a named function expression:
const greet = function sayHi() {
console.log("Hi");
};
The inner name can help with recursion and debugging.
6. Reassigning function variables accidentally
Broken code:
var processData = function() {
return "done";
};
processData = 42;
Now processData is no longer callable.
Avoid this with const when possible.
Comparisons
| Feature | Function Declaration | Function Expression |
|---|---|---|
| Basic syntax | function name() {} | var name = function() {} |
| Hoisted fully | Yes | No |
| Can be called before definition | Yes | Usually no |
| Stored in a variable | Not primarily | Yes |
| Good for callbacks | Possible, but less common inline | Very common |
| Can be anonymous | No | Yes |
| Conditional definition | Less natural | More natural |
| Readability for top-level helpers | Often very good | Good, but sometimes noisier |
Function declaration vs function expression with const
| Pattern | Example | Notes |
|---|---|---|
| Declaration | function sum() {} | Best for reusable named functions |
Expression with var | var sum = function() {} | Older style, weaker scoping |
Expression with const | const sum = function() {} | Modern and safer |
Which should you choose?
- Choose function declarations for clear named functions that represent core logic.
- Choose function expressions when passing functions around, creating callbacks, or assigning behavior dynamically.
- Avoid
varin modern JavaScript unless you specifically need legacy behavior.
Cheat Sheet
Quick reference
Function declaration
function greet() {
console.log("Hello");
}
- hoisted with full function body
- can be called before definition
- good for reusable named functions
Function expression
const greet = function() {
console.log("Hello");
};
- function is created as a value
- assignment happens at runtime
- cannot be called before assignment
- useful for callbacks and dynamic assignment
Hoisting rule
hello(); // works
function hello() {}
hello(); // error
var hello = function() {};
Modern recommendation
- prefer
function name() {}for top-level named helpers - prefer
const name = function() {}for assigned functions - prefer
constovervarin modern code
Remember
- declarations are hoisted fully
vardeclarations are hoisted, not their assigned function values- both forms create callable functions after they are properly defined
FAQ
Is var fn = function() {} the same as function fn() {}?
No. Both create functions, but they differ in hoisting and how they are defined. A function declaration is available earlier in the scope, while a function expression assigned to var is not callable until assignment happens.
Which is better in JavaScript: function declaration or function expression?
Neither is always better. Function declarations are great for main named functions. Function expressions are better when a function is being passed, stored, or chosen dynamically.
Why can function declarations be called before they are written?
Because JavaScript hoists the full function declaration during scope setup.
Why does a function expression with var fail before its definition?
Because only the variable declaration is hoisted. The variable exists, but its value is undefined until the assignment line runs.
Can a function expression have a name?
Yes.
const fn = function helper() {
return "ok";
};
This can help with recursion and debugging.
Should I still use var for function expressions?
Usually no. In modern JavaScript, const or let is preferred because block scoping is safer and clearer.
Can both be used as callbacks?
Technically yes, but function expressions are more commonly used inline as callbacks.
Is there anything one can do that the other cannot?
In practice, function expressions are more flexible because they fit naturally anywhere an expression is allowed. Function declarations are better for hoisted named definitions.
Mini Project
Description
Build a small utility that formats messages differently depending on the user's role. This project demonstrates when a function expression is useful for dynamic assignment and when a function declaration is useful for stable reusable helpers.
Goal
Create a script that selects one formatting function for admins and another for regular users, then prints a formatted message.
Requirements
- Create a reusable function declaration to validate that a username is present.
- Use a function expression assigned to a variable to choose different formatting behavior.
- Print a formatted message for at least two different user roles.
- Prevent formatting if the username is missing.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.