Function Expression
Learn what function expressions are, how they differ from function declarations, and when to use them.
Function Expression
In the previous topic we declared functions like this:
function greet() {
console.log("Hello!");
}But in JavaScript, functions are values — just like numbers, strings, and booleans. You can store them in variables, pass them around, and use them wherever a value is expected.
A function expression is simply a function stored in a variable.
const greet = function() {
console.log("Hello!");
};
greet(); // Hello!The function has no name of its own — it lives inside the variable greet. You call it the same way — greet() — but it is defined differently.
Syntax
const functionName = function() {
// code to run
};Notice the semicolon at the end — ;. Because this is a variable assignment, it ends like any other variable declaration.
With parameters and a return value:
const add = function(a, b) {
return a + b;
};
console.log(add(10, 5)); // 15Function Declaration vs Function Expression
They look similar but behave differently in one important way — hoisting.
// ✅ Function declaration — can be called before it is defined
sayHello(); // Hello!
function sayHello() {
console.log("Hello!");
}// ❌ Function expression — cannot be called before it is defined
greet(); // ReferenceError: Cannot access 'greet' before initialization
const greet = function() {
console.log("Hello!");
};Function declarations are hoisted — JavaScript moves them to the top before running the code. Function expressions are not — the variable exists but the function value is not assigned until that line runs.
We cover hoisting in full detail in its own topic. For now just remember — with function expressions, define first, call after.
| Function Declaration | Function Expression | |
|---|---|---|
| Syntax | function name() {} | const name = function() {} |
| Hoisted? | ✅ Yes | ❌ No |
| Has its own name? | ✅ Yes | Not required |
Ends with ;? | ❌ No | ✅ Yes |
Named Function Expression
A function expression can have its own internal name — but that name is only accessible inside the function itself.
const factorial = function calculate(n) {
if (n <= 1) return 1;
return n * calculate(n - 1); // can use 'calculate' inside
};
console.log(factorial(5)); // 120
console.log(typeof calculate); // ReferenceError — not accessible outsideThe internal name calculate is useful for recursion — calling the function from within itself. Outside the function only factorial exists.
Functions as Values
This is where function expressions become truly powerful. Because the function is stored in a variable — it is a value. And values can be passed around.
Storing in an object
const calculator = {
add: function(a, b) { return a + b; },
subtract: function(a, b) { return a - b; },
multiply: function(a, b) { return a * b; },
};
console.log(calculator.add(10, 5)); // 15
console.log(calculator.subtract(10, 5)); // 5
console.log(calculator.multiply(10, 5)); // 50Passing a function to another function
function runTwice(fn) {
fn();
fn();
}
const sayHi = function() {
console.log("Hi!");
};
runTwice(sayHi);
// Hi!
// Hi!A function passed to another function as an argument is called a callback. This is one of the most important patterns in JavaScript — used everywhere from array methods to event listeners to async code.
Returning a function from a function
function createMultiplier(multiplier) {
return function(number) {
return number * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15createMultiplier returns a new function every time it is called. double and triple are function expressions born at runtime with different behavior baked in. This pattern is called a closure — covered in depth in the Advanced section.
A Real Example — Flexible Greeting
function buildGreeting(timeOfDay) {
if (timeOfDay === "morning") {
return function(name) {
console.log(`Good morning, ${name}! Hope your day goes well.`);
};
} else if (timeOfDay === "evening") {
return function(name) {
console.log(`Good evening, ${name}! Hope you had a great day.`);
};
} else {
return function(name) {
console.log(`Hello, ${name}!`);
};
}
}
const morningGreet = buildGreeting("morning");
const eveningGreet = buildGreeting("evening");
morningGreet("Ali"); // Good morning, Ali! Hope your day goes well.
eveningGreet("Sara"); // Good evening, Sara! Hope you had a great day.buildGreeting returns a different function depending on the time of day. Each returned function is a function expression created and returned on the fly.
When to Use Function Expression vs Declaration
Both are valid — the choice depends on the situation.
// Use declaration for main, named, reusable functions
function calculateTotal(price, tax) {
return price + tax;
}
// Use expression when passing functions around
const numbers = [3, 1, 4, 1, 5];
numbers.sort(function(a, b) {
return a - b;
});
// Use expression when storing functions in objects
const validator = {
isEmail: function(value) {
return value.includes("@");
},
isEmpty: function(value) {
return value.trim() === "";
}
};| Situation | Use |
|---|---|
| Top level reusable utility function | Declaration |
| Function passed as a callback | Expression |
| Function stored in an object | Expression |
| Function returned from another function | Expression |
| You need to call it before defining it | Declaration |
In modern JavaScript, arrow functions have largely replaced function expressions for callbacks and inline functions. We cover arrow functions in the next topic — and you will see why they are preferred.
Summary
- A function expression stores a function in a variable —
const fn = function() {} - Unlike declarations, function expressions are not hoisted — define before calling
- Always end with a semicolon since it is a variable assignment
- Functions are values — they can be stored in objects, passed as arguments, and returned from other functions
- A function passed to another function is called a callback
- Use declarations for top level reusable functions, use expressions when passing functions around or storing them in objects