Function Declaration vs Function Expression in JS

In JavaScript, functions can be defined primarily using function declarations or function expressions. While both achieve the goal of executing reusable blocks of code, they differ significantly in their syntax, how the JavaScript engine loads them into memory through hoisting, when they are evaluated, and their suitability for different programming patterns like callbacks and closures.

Syntax Differences

A function declaration is a standalone statement that begins with the function keyword and must include an identifier (the function’s name).

function greet() {
  return "Hello, World!";
}

A function expression defines a function as part of a larger expression, typically by assigning it to a variable. These can be anonymous (without a name) or named, and they can also be written using arrow function syntax.

// Anonymous function expression
const greet = function() {
  return "Hello, World!";
};

// Named function expression
const greetNamed = function greetMessage() {
  return "Hello, World!";
};

// Arrow function expression
const greetArrow = () => "Hello, World!";

Key Differences

1. Hoisting Behavior

The most critical technical distinction between the two is hoisting.

sayHello(); // Output: "Hello!"

function sayHello() {
  console.log("Hello!");
}
sayGoodbye(); // ReferenceError: Cannot access 'sayGoodbye' before initialization

const sayGoodbye = function() {
  console.log("Goodbye!");
};

2. Execution and Evaluation Timing

3. Conditional Declarations

Function expressions provide greater flexibility when creating functions conditionally.

let logMessage;

if (isProduction) {
  logMessage = function(msg) { /* silent or production log */ };
} else {
  logMessage = function(msg) { console.log(msg); };
}

While modern JavaScript allows function declarations inside block scopes, behavior can vary depending on strict mode and may lead to inconsistent results across different JavaScript environments.

4. Immediately Invoked Function Expressions (IIFE)

Function expressions can be executed immediately after they are defined, which is useful for creating private scopes. Function declarations cannot be immediately invoked in this manner without syntax errors.

(function() {
  const privateVar = "Secret";
  console.log("Executed immediately");
})();

When to Use Each