In JavaScript, functions are first-class citizens — you can store them in variables, pass them as arguments, and return them from other functions. Function expressions unlock functional programming patterns that make JavaScript powerful and flexible.
Day 26 / 180
Beginner Phase
🕐13 min read
💻8 code examples
🎯3 practice tasks
📝5 quiz questions
Here is the key difference between function declarations and function expressions:
Function Declaration vs Function Expression
// ✅ Function Declaration — can be called BEFORE definition (hoisted)
sayHello(); // This works! Output: "Hello!"functionsayHello() {
console.log("Hello!");
}
// ❌ Function Expression — CANNOT be called BEFORE definition
sayGoodbye(); // ❌ ERROR! sayGoodbye is not defined yetconst sayGoodbye = function() {
console.log("Goodbye!");
};
sayGoodbye(); // ✅ This works — called AFTER definition// This difference matters! Function expressions are NOT hoisted.
Function expressions treat functions like any other value — you can assign them to variables, store them in arrays, pass them to other functions, and even return them from functions. This is a fundamental concept in JavaScript that enables callbacks, higher-order functions, and functional programming. Today, I'll show you how function expressions work, how they differ from declarations, and why you'd choose one over the other.
1. The Problem — Need for Flexible Functions
Function declarations are great, but they have limitations. What if you want to create a function conditionally? What if you want to store a function in an object or array? What if you want to pass a function as an argument to another function? Function declarations alone can't do these things elegantly. Function expressions solve these problems by treating functions as values.
In JavaScript, functions are first-class citizens. This means functions are treated like any other data type — numbers, strings, booleans, arrays, and objects. You can assign them to variables, store them in data structures, pass them as arguments, and return them from other functions. This flexibility is what makes JavaScript so powerful for functional programming.
What Function Expressions Enable
// 1. Conditional function creationlet greet;
if (userLanguage === "urdu") {
greet = function() { console.log("السلام علیکم"); };
} else {
greet = function() { console.log("Hello"); };
}
// 2. Storing functions in arraysconst operations = [
function(a, b) { return a + b; }, // addfunction(a, b) { return a - b; }, // subtractfunction(a, b) { return a * b; } // multiply
];
console.log(operations[0](5, 3)); // 8// 3. Passing functions as arguments (callbacks)functionprocessUser(userId, callback) {
const user = { id: userId, name: "Waheed" };
callback(user);
}
processUser(1, function(user) {
console.log(`User: ${user.name}`);
});
// 4. Returning functions from functionsfunctionmultiplier(factor) {
returnfunction(number) {
return number * factor;
};
}
const double = multiplier(2);
console.log(double(5)); // 10
💡 The insight: Function expressions treat functions as values — just like numbers or strings. This means you can store them, pass them around, and use them dynamically. This is the foundation of callbacks, event handlers, and functional programming in JavaScript.
2. Function Expressions — Assigning Functions to Variables
A function expression is when you create a function and assign it to a variable. The function itself can be named (named function expression) or anonymous (no name). The variable name is what you use to call the function. Unlike function declarations, function expressions are not hoisted — you cannot call them before they are defined.
The syntax is straightforward: const variableName = function(parameters) { // code };. Note the semicolon at the end — function expressions are statements, so they end with a semicolon like any other assignment.
Function Expression Examples
// Basic function expression (anonymous function)const square = function(x) {
return x * x;
};
console.log(square(5)); // 25// Named function expression (has a name inside for debugging)const factorial = functionfact(n) {
if (n <= 1) return1;
return n * fact(n - 1); // Can use the name recursively
};
console.log(factorial(5)); // 120// Function expression with multiple parametersconst divide = function(a, b) {
if (b === 0) {
return"Cannot divide by zero";
}
return a / b;
};
console.log(divide(10, 2)); // 5// Reassigning function expressions (variables can change)let greet = function() {
console.log("Hello");
};
greet(); // Hello
greet = function() {
console.log("Hola");
};
greet(); // Hola (function changed!)// Using const prevents reassignment (recommended)const add = function(a, b) {
return a + b;
};
// add = function() {}; // ❌ Error! Cannot reassign const
📝 QUIZ 1 & 2Test Your Understanding
Question 1: What is a function expression?
Question 2: Are function expressions hoisted?
3. Anonymous Functions — Functions Without Names
An anonymous function is a function without a name. You typically use them when you need a function for a short time and don't need to refer to it by name elsewhere. Anonymous functions are commonly used as callbacks, event handlers, and immediately invoked function expressions (IIFEs).
The term "anonymous" means "nameless." These functions are created on the fly and often passed directly to other functions. They are perfect for one-time use scenarios where creating a named function would be unnecessary overhead.
Anonymous Function Examples
// Anonymous function assigned to a variable (still anonymous, called via variable)const greet = function(name) { // No name after 'function' keyword
console.log(`Hello, ${name}`);
};
// Anonymous function as a callback (most common use)
[1, 2, 3].forEach(function(num) { // Anonymous callback
console.log(num * 2);
});
// Anonymous function as an event handler
document.addEventListener("click", function() {
console.log("Button clicked!");
});
// IIFE (Immediately Invoked Function Expression) — runs right away
(function() {
console.log("This runs immediately!");
})();
// IIFE with parameters
(function(name) {
console.log(`Hello, ${name}`);
})("Waheed");
// Anonymous function returned from another functionfunctioncreateCounter() {
let count = 0;
returnfunction() { // Returns an anonymous function
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
4. Function Declarations vs Function Expressions — Key Differences
Understanding the differences between function declarations and function expressions is crucial for writing predictable code. The most important difference is hoisting — declarations are hoisted, expressions are not. This affects when and where you can call your functions.
Declaration vs Expression Comparison
// ---------- HOISTING DIFFERENCE ----------// ✅ Function Declaration — HOISTED (works!)
sayHello(); // This works! Output: "Hello"functionsayHello() {
console.log("Hello");
}
// ❌ Function Expression — NOT HOISTED (error!)
sayGoodbye(); // ❌ ReferenceError: Cannot access before initializationconst sayGoodbye = function() {
console.log("Goodbye");
};
// ---------- NAMING DIFFERENCE ----------// Declaration has a name (required)functionadd(a, b) { return a + b; }
// Expression can be anonymous (no name) or namedconst subtract = function(a, b) { return a - b; }; // Anonymousconst multiply = functionmult(a, b) { return a * b; }; // Named// ---------- WHEN TO USE EACH ----------// Use Declaration when:// 1. You need a reusable function available everywhere// 2. You want hoisting (call before definition)// 3. The function is a standalone utility// Use Expression when:// 1. You need to assign a function conditionally// 2. You're passing a function as a callback// 3. You want to create an IIFE// 4. You need to store functions in data structures
Feature
Function Declaration
Function Expression
Hoisting
✅ Yes (fully hoisted)
❌ No (not hoisted)
Can be anonymous?
❌ No (must have name)
✅ Yes (can be anonymous)
Can be reassigned?
❌ No (fixed reference)
✅ Yes (if using let)
Can be used as callback?
✅ Yes (by name)
✅ Yes (directly)
Can be IIFE?
❌ No
✅ Yes (wrap in parentheses)
📝 QUIZ 3 & 4Test Your Understanding
Question 3: Which of the following is a key difference between function declarations and function expressions?
Question 4: What is an IIFE?
5. Common Mistakes to Avoid
Mistakes & Fixes
// ❌ MISTAKE 1: Calling function expression before definition
sayHi(); // ❌ ERROR! sayHi is not defined yetconst sayHi = function() {
console.log("Hi!");
};
// ✅ FIX: Define before callingconst sayHi = function() {
console.log("Hi!");
};
sayHi(); // ✅ Works!// ❌ MISTAKE 2: Forgetting semicolon after function expressionconst add = function(a, b) {
return a + b;
} // ❌ Missing semicolon (can cause issues in minified code)// ✅ FIX: Add semicolonconst add = function(a, b) {
return a + b;
}; // ✅ Semicolon added// ❌ MISTAKE 3: Using const when you need to reassignconst getValue = function() {
return42;
};
getValue = function() { // ❌ Error! Cannot reassign constreturn100;
};
// ✅ FIX: Use let if you need to reassignlet getValue = function() {
return42;
};
getValue = function() { // ✅ Works with letreturn100;
};
// ❌ MISTAKE 4: Forgetting parentheses for IIFEfunction() {
console.log("This causes a syntax error");
}(); // ❌ Syntax error without wrapping parentheses// ✅ FIX: Wrap the function in parentheses
(function() {
console.log("This works!");
})(); // ✅ Correct IIFE syntax
6. Best Practices — When to Use Each
🎯 Use Function Declarations for Global Utilities
For functions that are used throughout your code (like helper utilities), function declarations are great because hoisting makes them available anywhere. Example: function formatDate(date) { ... }
📦 Use Function Expressions for Callbacks
When passing a function to another function (like array methods or event listeners), function expressions (especially anonymous ones) are perfect: arr.map(function(item) { return item * 2; })
🔒 Prefer const for Function Expressions
When using function expressions, use const instead of let to prevent accidental reassignment. This makes your intent clear and prevents bugs.
📝 Name Your Function Expressions for Debugging
Named function expressions appear in stack traces, making debugging easier. Instead of const add = function(a,b) {...}, use const add = function add(a,b) {...}.
🎭 Use IIFE for Module Patterns
IIFEs (Immediately Invoked Function Expressions) are great for creating private scopes and module patterns. They run once and don't pollute the global namespace.
7. Try It Yourself — Function Expression Playground
Experiment with function expressions below. See how they can be stored, passed, and used dynamically.
✏️ Function Expression Playground
HTML
JAVASCRIPT
LIVE PREVIEW
💡 Functions stored in an object — try different operations!
8. Practice Tasks
Task 1 — Easy: Function Expression Greeting
Create a function expression called greet that takes a name parameter and returns "Hello, [name]!". Test it with "Ali" and "Sara".
Task 2 — Medium: Array of Functions
Create an array called mathOperations that contains three function expressions: add (a+b), subtract (a-b), and multiply (a*b). Then write code to call each function with numbers 10 and 5, logging the results.
Task 3 — Hard: Function Factory
Write a function createMultiplier(multiplier) that returns a new function that multiplies any number by the multiplier. Use this to create a double function (multiplier=2) and a triple function (multiplier=3). Test with the number 7.
📝 FINAL QUIZTest Your Mastery
Question 5: What will be the output of the following code?
const multiply = function(a, b) {
return a * b;
};
console.log(multiply(4, 3));