Skip to Content
Course content

28: Function Declarations vs Expressions

Click on the "Edit" button in the top corner of the screen to edit your slide content.

If you've been writing JavaScript for a few weeks, you've probably noticed there are two main ways to create a function. You can use a declaration—the classic function doSomething() {}—or an expression, where you assign a function to a variable, like const doSomething = function() {}. At first glance, they look like two different ways to achieve the same result. I'll let you in on a secret: they aren't the same, and using the wrong one in a large codebase is a great way to introduce bugs that are a nightmare to debug.

The "Magic" that confuses new devs

The biggest difference is something called hoisting. When you use a function declaration, JavaScript moves the entire function definition to the top of its scope during the compilation phase. To a beginner, this looks like a superpower. You can call a function on line 5, even though you didn't actually write the function until line 50.

// This works perfectly, which is actually the problem
const total = calculateTax(100); 

function calculateTax(amount) {
    return amount * 1.15;
}

I used to think this was convenient, but in a professional environment, it's a trap. When I'm reviewing a pull request and I see a function call at the top of a 200-line file, I have to go hunting through the code to find where that logic actually lives. It breaks the natural "top-to-bottom" flow of reading a script. Worse, if you accidentally declare another function with the same name later in the file, JavaScript will just overwrite the first one without warning you. It's far too permissive.

Locking it down with expressions

The "better" way—the way we actually write production code—is to use function expressions, usually paired with const. Because you're assigning the function to a variable, it follows the same rules as any other variable: it isn't hoisted. If you try to call it before the line where it's defined, the engine will throw a ReferenceError.

// This will crash, and that's a good thing
const total = applyDiscount(100); 

const applyDiscount = function(amount) {
    return amount * 0.90;
};

By forcing the function to be defined before it's used, you're making the dependency graph of your code explicit. You can read the file from top to bottom and know exactly what is available at any given moment. Plus, using const ensures that you can't accidentally reassign that function to something else later in your script. It turns a runtime mystery into a predictable structure.

When expressions become powerful

Beyond just avoiding hoisting, expressions open the door to patterns that declarations simply can't handle. Since a function expression is just a value, you can pass it as an argument to another function. This is the bread and butter of JavaScript. Whether you're using .map(), .filter(), or adding an event listener to a button, you're using expressions.

You've likely seen arrow functions (() => {}) by now. Those are just a concise syntax for function expressions. You can't "hoist" an arrow function. This forces a discipline in your architecture: you define your helper utilities first, and your main execution logic last. It sounds like a small detail, but when you're working on a team with five other engineers, that predictability is the only thing keeping the project from collapsing into chaos.




📋 Practical Task

Refactoring the Loyalty Point Calculator

You've been handed a legacy script for a loyalty points system. The previous developer relied heavily on function declarations and hoisting, making the code hard to follow. Your task is to refactor the code to use const function expressions.

Requirements:

  • Convert the calculatePoints and formatPointsMessage function declarations into function expressions using const.
  • Rearrange the code so that the functions are defined before they are called.
  • Ensure the final output is logged to the console correctly.
// REFACTOR THIS CODE
console.log(formatPointsMessage(calculatePoints(500)));

function calculatePoints(spend) {
    return spend * 0.1;
}

function formatPointsMessage(points) {
    return `You have earned ${points} loyalty points!`;
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.