Javascript

Why can I use a function before its defined in JavaScript

25 September 2026 · 7 min read

Why can I use a function before its defined in JavaScript

One of the most intriguing and often confusing behaviors for developers new to JavaScript is the ability to invoke a function seemingly before it has been declared in the code. This phenomenon can lead to questions like, “Why can I use a function before it’s defined in JavaScript?” It appears to defy the typical top-to-bottom execution model seen in many other programming languages. This unique characteristic is not magic, but rather a fundamental concept known as “hoisting.” Understanding JavaScript hoisting is crucial for writing predictable and robust code, especially when dealing with function declarations and variable scopes. This article will demystify this powerful feature, explaining the underlying mechanisms of the JavaScript engine and offering practical insights into how it affects your code.

Understanding JavaScript Hoisting: The Core Concept

JavaScript hoisting refers to the mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase, before the code is executed. It’s important to note that this “movement” is conceptual; the code isn’t physically rewritten. Instead, the JavaScript engine processes declarations first, allocating memory for them, and only then begins to execute the rest of the code line by line. This two-phase processing is what allows you to call a function declaration before its appearance in your script.

This process means that when the JavaScript engine encounters a function declaration, it immediately makes that function available throughout its entire scope, whether it’s global or within another function. For instance, if you define a function at the bottom of your script, you can still call it from the very top. This behavior differs significantly from how function expressions or arrow functions are handled, which are treated more like variables and are only accessible after their definition point in the execution flow. Grasping this distinction is key to navigating JavaScript’s sometimes counter-intuitive behavior.

As per the Mozilla Developer Network (MDN), “In JavaScript, a variable (or function) can be used before it has been declared.” This authoritative source reinforces the concept that hoisting is an inherent part of the language’s design, not an error or a bug. It’s a feature that, when understood, can be leveraged effectively, but when misunderstood, can lead to subtle bugs and unexpected outcomes in your applications. Mastering hoisting is a step towards becoming a more proficient JavaScript developer.

Function Declarations vs. Function Expressions

The core difference in hoisting behavior lies between function declarations and function expressions. A function declaration is defined using the function keyword followed by a function name, like function myFunction() { ... }. These are fully hoisted, meaning both their declaration and their definition are processed and made available in memory before any code execution. This is why you can call myFunction() at the top of your script even if its definition appears later.

Conversely, a function expression assigns an anonymous function to a variable, for example, const myFunc = function() { ... }; or const myArrowFunc = () => { ... };. In this case, only the variable (myFunc or myArrowFunc) is hoisted, and like other variables declared with var, it’s initialized with undefined. The function’s actual definition is not hoisted. Therefore, attempting to call myFunc() before its assignment line would result in a TypeError because myFunc would be undefined at that point. This distinction is critical for predicting how your code will behave.

Consider this example: a common pitfall occurs when developers mistakenly assume function expressions behave like declarations. If you write sayHello(); const sayHello = function() { console.log("Hello!"); };, you’ll encounter an error. This is because sayHello is only a variable declaration at the point of the call, not yet assigned its function value. Understanding this nuance is vital for debugging “ReferenceError: Cannot access ‘…’ before initialization” or “TypeError: … is not a function” messages, especially when working with modern JavaScript features like const and let.

The JavaScript Execution Context and How Hoisting Works

To truly understand why functions can be used before their definition, we must delve into the JavaScript execution context. When JavaScript code runs, an execution context is created. This context has two distinct phases: the “creation phase” and the “execution phase.” Hoisting predominantly occurs during the creation phase. During this phase, the JavaScript engine scans the code, identifies all variable and function declarations, and sets them up in memory.

Specifically, for function declarations, the entire function definition (its name and body) is stored in the memory heap, and a reference to it is placed in the current lexical environment (also known as the variable environment) of the execution context. This means that by the time the execution phase begins, all function declarations are already fully available and callable. This pre-processing step is what gives the illusion of “moving” declarations to the top. It’s akin to an interpreter doing a first pass to catalog all the definitions it needs before it starts running the actual instructions.

For example, if you have console.log(calculateSum(5, 3)); function calculateSum(a, b) { return a + b; }, during the creation phase, calculateSum is fully set up in memory. Then, during the execution phase, when console.log(calculateSum(5, 3)) is encountered, the calculateSum function is already known and can be invoked successfully. This systematic approach by the JavaScript engine ensures that the necessary components for code execution are in place before any operations are performed, contributing to the language’s dynamic nature.

The Global Object and Variable Environment

Within the execution context, the variable environment is a crucial component that stores all variables and function declarations for the current scope. In the global execution context, this environment is essentially the global object (window in browsers, global in Node.js). When a function declaration is hoisted, it becomes a property of this global object or the local scope’s variable environment, depending on where it’s declared.

This is why you can often access globally declared functions directly on the window object in a browser. This direct attachment to the global object highlights how hoisting makes declarations available across the entire script. It’s a powerful feature that allows for flexible code organization, but also one that requires careful consideration to avoid polluting the global namespace.

Understanding the variable environment and its interaction with the global object is fundamental to grasping not only hoisting but also concepts like scope chain and closures. It provides the foundational knowledge for comprehending how JavaScript manages memory and variable accessibility throughout its lifecycle. For a deeper dive, resources like ECMAScript Language Specification offer comprehensive details on execution contexts.

Infographic: JavaScript Hoisting Flow (Creation vs. Execution Phase)
Practical Implications and Common Pitfalls ------------------------------------------

While hoisting offers flexibility, it can also introduce subtle bugs if not fully understood. One common pitfall arises when mixing function declarations with function expressions, especially when refactoring code. Developers might inadvertently change a function declaration into an expression, only to find that calls made before the expression’s definition now fail. This highlights the importance of consistent coding style and understanding the implications of each function definition method.

Another area of concern is variable hoisting. While function declarations hoist their entire definition, variables declared with var are only hoisted in terms of their declaration, not their initialization. They are assigned undefined until the execution reaches their actual assignment. This can lead to unexpected undefined values if variables are accessed before their assignment. For example, console.log(myVar); var myVar = "hello"; will output undefined, not an error. This behavior is often cited as a Question & Answer :

This code always works, even in different browsers:

function fooCheck() { alert(internalFoo()); // We are using internalFoo() here... return internalFoo(); // And here, even though it has not been defined... function internalFoo() { return true; } //...until here! } fooCheck(); 

I could not find a single reference to why it should work, though. I first saw this in John Resig’s presentation note, but it was only mentioned. There’s no explanation there or anywhere for that matter.

Could someone please enlighten me?

The function declaration is magic and causes its identifier to be bound before anything in its code-block* is executed.

This differs from an assignment with a function expression, which is evaluated in normal top-down order.

If you changed the example to say:

var internalFoo = function() { return true; }; 

it would stop working.

The function declaration is syntactically quite separate from the function expression, even though they look almost identical and can be ambiguous in some cases.

This is documented in the ECMAScript standard, section 10.1.3. Unfortunately ECMA-262 is not a very readable document even by standards-standards!

*: the containing function, block, module or script.