Function Expression vs Declaration: Which to Choose in JavaScript?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why does this question torment even experienced developers?

\n

If you've ever written in JavaScript, you've surely encountered both of these ways to declare functions. They look similar, but behave completely differently. On Stack Overflow, this question has gathered thousands of views and dozens of pages of discussion. Why? Because not understanding the difference between var functionName = function() {} and function functionName() {} leads to bugs that are hard to catch.

\n

Today, we will finally and forever sort out this topic. You will learn what function declaration and function expression are, how hoisting works, and when to use which method. Let's go!

\n\n

What lies behind the syntax?

\n

Let's start with the basics. The first option is a Function Declaration:

\n
function greet() {\n    console.log('Hello!');\n}
\n

The second is a Function Expression:

\n
const greet = function() {\n    console.log('Hello!');\n};
\n

Notice: in the first case, the function has a name and stands at the beginning of the line. In the second, we assign an anonymous function to the variable greet. But the most interesting part begins when we look at how JavaScript processes these declarations.

\n\n

The main difference: Hoisting

\n

Hoisting is a JavaScript mechanism where declarations of variables and functions are moved to the top of their scope before code execution. But it works differently for declarations and expressions.

\n\n

Function Declaration is hoisted entirely

\n

When you use function functionName() {}, JavaScript "hoists" the entire function declaration to the top. This means you can call the function before it is declared in the code:

\n
sayHello(); // "Hello!"\n\nfunction sayHello() {\n    console.log('Hello!');\n}
\n

The code will execute without errors. This is convenient, but can be confusing for beginners.

\n\n

Function Expression is not hoisted

\n

With var functionName = function() {}, the story is different. Only the variable declaration is hoisted, not its value. The function stays in place:

\n
sayHello(); // TypeError: sayHello is not a function\n\nvar sayHello = function() {\n    console.log('Hello!');\n};
\n

Why is that? Because var hoists the declaration of the variable sayHello (with the value undefined), and the assignment of the function happens only on the line with the expression. Therefore, before that line, sayHello is undefined, and attempting to call it as a function results in an error.

\n\n

By the way, if you replace var with let or const, the error will be different — ReferenceError: Cannot access 'sayHello' before initialization. This is because let and const are not initialized until the moment of declaration (the so-called "temporal dead zone").

\n\n

Scope: another stumbling block

\n

Both function declaration and function expression follow scope rules. But there is a nuance.

\n\n

Function Declaration is visible within the block

\n

Although function declaration is hoisted, its scope is limited to the block (in strict mode):

\n
'use strict';\nif (true) {\n    function greet() {\n        console.log('Inside the block');\n    }\n    greet(); // "Inside the block"\n}\ngreet(); // ReferenceError: greet is not defined (in strict mode)
\n

In non-strict mode, such a declaration will "leak" out, but relying on this is not recommended.

\n\n

Function Expression lives in its variable

\n

With function expression, everything is predictable: the function is only accessible where the variable is accessible. If you move

Blogs

Book Recommendations