JavaScript tutorials > JavaScript Basics > Functions > What is the difference between function declarations and expressions?

What is the difference between function declarations and expressions?

In JavaScript, both function declarations and function expressions are ways to define functions, but they differ in how they are parsed and when they are available for use. Understanding these differences is crucial for writing clean and efficient JavaScript code.

Basic Syntax

Function Declaration: Begins with the function keyword followed by the function name, parameters in parentheses, and the function body enclosed in curly braces.

Function Expression: Assigns an anonymous or named function to a variable. The function keyword is followed by optional function name, parameters in parentheses, and the function body.

 // Function Declaration
 function greetDeclaration(name) {
   return 'Hello, ' + name + '!';
 }

 // Function Expression
 const greetExpression = function(name) {
   return 'Hello, ' + name + '!';
 };

Hoisting

Function Declarations: Are hoisted, meaning they are moved to the top of their scope during compilation. You can call a function declaration before it appears in the code.

Function Expressions: Are not hoisted in the same way as function declarations. They behave like any other variable assignment. You cannot call a function expression before it's defined in the code.

// Hoisting Example

console.log(greetDeclaration('Alice')); // Works fine

function greetDeclaration(name) {
  return 'Hello, ' + name + '!';
}


console.log(greetExpression('Bob')); // Throws an error: Cannot access 'greetExpression' before initialization

const greetExpression = function(name) {
  return 'Hello, ' + name + '!';
};

Named vs. Anonymous Functions

Function Declarations: Are always named.

Function Expressions: Can be either named or anonymous. Named function expressions are useful for debugging and recursion.

// Named Function Expression
 const greetNamedExpression = function greet(name) {
   return 'Hello, ' + name + '!';
 };

 // Anonymous Function Expression
 const greetAnonymousExpression = function(name) {
   return 'Hello, ' + name + '!';
 };

Concepts Behind the Snippet

The core concept is understanding how JavaScript handles function definitions during its execution phase. Hoisting is a key difference. Knowing when a function is available is crucial for avoiding runtime errors.

Real-Life Use Case

Function Declarations: Useful when you need a function to be available throughout your entire script, regardless of its physical location in the code.

Function Expressions: Often used in callbacks (e.g., event listeners, setTimeout), immediately invoked function expressions (IIFEs), and assigning functions to object properties.

Example: An event listener attached using an anonymous function expression:

document.getElementById('myButton').addEventListener('click', function() { console.log('Button clicked!'); });

Best Practices

Use function declarations for top-level functions and core logic. Use function expressions when assigning functions to variables, passing them as arguments to other functions (callbacks), or creating closures.

Interview Tip

When asked about the difference, emphasize the concept of hoisting and how it affects code execution. Also, mention the use cases where one might be preferred over the other.

Example answer: "The main difference lies in hoisting. Function declarations are hoisted, so you can call them before they appear in your code. Function expressions are not hoisted in the same way, meaning you can only call them after they've been defined. Function expressions are also commonly used for callbacks and closures."

When to use them

Use Function Declarations when:

  • You need hoisting: The function needs to be available throughout the script, even before its declaration in the code.
  • For clarity and readability: Function declarations often make the code easier to read because the function's purpose is immediately apparent.

Use Function Expressions when:

  • Creating anonymous functions for callbacks or event listeners.
  • Creating closures to encapsulate data.
  • Assigning functions to object properties or as arguments to other functions.
  • You need more control over when the function is defined (e.g., conditionally defining a function).

Memory footprint

There's no significant difference in memory footprint between function declarations and function expressions themselves. The main difference lies in how they are handled during the compilation and execution phases.

However, the use of closures (which are often created with function expressions) can have implications for memory management. Closures capture variables from their surrounding scope, and these captured variables remain in memory even after the outer function has finished executing. This can potentially lead to memory leaks if closures are not used carefully. This applies to both function declarations and expressions when they're used to create closures, but it's a more common pattern with function expressions due to their frequent use in callbacks and event handlers.

Alternatives

Arrow functions (=>) provide a more concise syntax for defining functions, especially for short, single-expression functions. They are always expressions and do not have their own this context.

// Arrow Function
 const greetArrow = (name) => 'Hello, ' + name + '!';

Pros of Function Declarations

  • Hoisting allows functions to be called before their definition.
  • Improved code readability.

Cons of Function Declarations

  • Can lead to unexpected behavior if not used carefully with hoisting.
  • Less flexible for creating closures and assigning functions dynamically.

Pros of Function Expressions

  • More control over function definition (e.g., conditional definition).
  • Useful for creating closures and callbacks.
  • Can be anonymous, reducing namespace pollution.

Cons of Function Expressions

  • Not hoisted, requiring careful placement in the code.
  • Can be slightly less readable than function declarations if the function is long and complex.

FAQ

  • What is hoisting?

    Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their scope before code execution. However, only the declarations are hoisted, not the initializations (in the case of variables). Function declarations are fully hoisted (declaration and initialization), while function expressions are hoisted as variables (only the declaration part).

  • Can I use a function expression without assigning it to a variable?

    Yes, you can, typically in an Immediately Invoked Function Expression (IIFE): (function() { console.log('IIFE'); })();

  • Are arrow functions function declarations or function expressions?

    Arrow functions are always function expressions.