Why JavaScript Function Declarations Behave Differently Than Expressions

This article explains the crucial differences between JavaScript function declarations and function expressions, how hoisting affects their availability, and why misunderstanding these concepts can lead to unexpected bugs in your code.

21CTO
21CTO
21CTO
Why JavaScript Function Declarations Behave Differently Than Expressions

JavaScript functions are everywhere and powerful, allowing object‑oriented features such as encapsulation and inheritance, but they can also create subtle bugs if their behavior is not fully understood.

1) Function Declaration

function funDeclaration(type){
    return type==="Declaration";
}

2) Function Expression

var funExpression = function(type){
    return type==="Expression";
}

Although the two snippets look similar, the way JavaScript treats them is fundamentally different. A function declared with a declaration can be called before its definition because the declaration is hoisted during the parsing phase.

1   funDeclaration("Declaration"); // => true
2   function funDeclaration(type){
3       return type==="Declaration";
4   }

In contrast, a function created with an expression is assigned at runtime; it cannot be invoked before the assignment occurs.

1   funExpression("Expression"); // => error
2   var funExpression = function(type){
3       return type==="Expression";
4   }

The underlying reason is that function declarations are hoisted, while function expressions are evaluated only when the execution reaches the assignment statement.

The following diagram illustrates the hoisting behavior of the two code blocks:

To deepen the distinction, consider a more confusing example:

var sayHello;
console.log(typeof (sayHey)); // => function
console.log(typeof (sayHo)); // => undefined
if (true) {
    function sayHey() {
        console.log("sayHey");
    }
    sayHello = function sayHo() {
        console.log("sayHello");
    }
} else {
    function sayHey() {
        console.log("sayHey2");
    }
    sayHello = function sayHo() {
        console.log("sayHello2");
    }
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

Analysis: sayHey is a function declaration, so during parsing both sayHey definitions are hoisted; the second one overwrites the first, resulting in sayHey2 being logged. sayHello is a function expression; its assignment happens at runtime, so the first definition is used.

The code above is equivalent to the following simplified version:

var sayHello;
function sayHey() {
    console.log("sayHey");
}
function sayHey() {
    console.log("sayHey2");
}
if (true) {
    // hoisting...
    sayHello = function sayHo() {
        console.log("sayHello");
    }
} else {
    // hoisting...
    sayHello = function sayHo() {
        console.log("sayHello2");
    }
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

In summary, function declarations are hoisted and can be invoked anywhere within their scope, while function expressions are evaluated at runtime and become callable only after the assignment has executed. This subtle difference can easily introduce hard‑to‑detect bugs.

Below are visual step‑by‑step diagrams of the execution flow for sayHello and sayHey:

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScripthoistingfunction-declarationfunction-expression
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.