Question

JavaScript Function Expressions vs Function Declarations

javascriptfunctionmethodssyntax

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.

Take Quiz

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:

  • factorial is the variable holding the function
  • fact is 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

  1. JavaScript scans the scope.
  2. It finds the function declaration square.
  3. It hoists the full function definition.
  4. console.log(square(4)) runs.
  5. square(4) returns 16.

Now compare that with:

console.log(square(4));

var square = function(n) {
  return n * n;
};

What happens here

  1. JavaScript scans the scope.
  2. It finds var square and hoists only the variable declaration.
  3. At this point, square is undefined.
  4. console.log(square(4)) tries to call undefined as a function.
  5. JavaScript throws an error.
  6. 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");
});
Take Quiz

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 const or let over var for 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
  • var function 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

FeatureFunction DeclarationFunction Expression
Basic syntaxfunction name() {}var name = function() {}
Hoisted fullyYesNo
Can be called before definitionYesUsually no
Stored in a variableNot primarilyYes
Good for callbacksPossible, but less common inlineVery common
Can be anonymousNoYes
Conditional definitionLess naturalMore natural
Readability for top-level helpersOften very goodGood, but sometimes noisier

Function declaration vs function expression with const

PatternExampleNotes
Declarationfunction sum() {}Best for reusable named functions
Expression with varvar sum = function() {}Older style, weaker scoping
Expression with constconst 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 var in modern JavaScript unless you specifically need legacy behavior.
Take Quiz

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 const over var in modern code

Remember

  • declarations are hoisted fully
  • var declarations 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.

Take Quiz

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.
Take Quiz

Keep learning

Related questions

View more