In our last lesson, we explored the high-level components of the JavaScript runtime: the call stack, heap, and event loop. You learned that the call stack's job is to keep track of function calls. Now, we're going to zoom in and examine exactly what gets put on the call stack. This "thing" is called an Execution Context.
This lesson is fundamental to achieving the deep conceptual understanding you're aiming for. By tracing the lifecycle of an execution context—specifically its creation and execution phases—you'll build a precise mental model for how JavaScript evaluates your code. This knowledge is the key that unlocks a clear understanding of more advanced topics like hoisting, scope, and closures, which we will tackle next.
The Execution Context: A Code's Environment
Whenever the JavaScript engine runs a piece of code, it does so within an Execution Context. Think of it as an environment or a wrapper that the engine creates to manage the interpretation and execution of that code. There are two main types:
- Global Execution Context (GEC): The default or base context. It's created when your script first starts to run. There's only one GEC for your entire program.
- Function Execution Context (FEC): Created every single time a function is invoked (called).
The entire process of how JavaScript runs your code can be visualized as a sequence of creating and managing these contexts.

As the flowchart shows, every execution context has two distinct phases. Understanding this two-phase process is the most crucial part of this lesson.
The Two Phases: Creation and Execution
Before the JavaScript engine executes a single line of your code, it first does a quick scan to prepare the environment. This leads to two distinct phases for any execution context:
-
The Creation Phase (or Memory Creation Phase): The engine doesn't execute any code. Instead, it scans the code for variable and function declarations and sets up memory for them.
- It creates a Variable Object (or Environment Record) to store these declarations.
- It establishes the Scope Chain to handle variable lookups (more on this in a future lesson).
- It determines the value of the
thiskeyword.
-
The Execution Phase: The engine runs your code line by line, executing statements and assigning the actual values to the variables it set up during the creation phase.
Let's see what specifically happens in each phase.
The Ultimate Guide to Hoisting, Scopes, and Closures in ...
This article provides a very clear breakdown of the responsibilities of each phase.
In the middle of the page, find the numbered list that begins "Create a global object". Read these four points carefully. This list details what the engine does during the Creation phase. The paragraph immediately following it describes the Execution phase.
To summarize the key points from your reading: during the Creation Phase, function declarations are stored in memory in their entirety, while variables declared with var are also stored but initialized with a value of undefined. Then, during the Execution Phase, the code runs, and the variables are assigned their actual values. This two-step process is the mechanism behind hoisting, which we'll explore in the next lesson.
Tracing a Function Call
Now, let's trace what happens when we call a function. The process begins in the Global Execution Context's execution phase.
- The engine is executing code in the GEC.
- It encounters a function invocation, for example,
myFunction(). - The engine pauses its work in the GEC and creates a brand new Function Execution Context (FEC) for
myFunction. - This new FEC is pushed onto the top of the Call Stack.
- The FEC goes through its own Creation and Execution phases.
- Once the function completes (e.g., hits a
returnstatement or the final curly brace}), its FEC is popped off the call stack. - Control returns to the previous context on the stack (in this case, the GEC), which resumes its execution from where it left off.
This transition from the GEC to a new FEC is a critical moment.

The main difference between a GEC and an FEC during the creation phase is that the FEC creates an arguments object, which is an array-like object containing all the arguments passed to the function. It does not create a new global object.
How Execution Context Works in JavaScript – A Handbook ...
This article gives a more detailed look at the Function Execution Context.
Read the section "Function Execution Context". Pay close attention to the comparison with the Global Execution Context and the role of the arguments object.
A Step-by-Step Walkthrough
The best way to solidify this concept is to trace the execution of a script with nested functions, watching the call stack grow and shrink.
Let's analyze the following code:
var a = 1;
function one() {
console.log(a);
two();
}
function two() {
var b = 2;
console.log(b);
three();
}
function three() {
let c = 3;
const d = 4;
console.log(c + d);
}
one();
We'll use a detailed guide to walk through this code step-by-step, observing how each execution context is created, executed, and destroyed.
How Execution Context Works in JavaScript – A Handbook ...
This article provides an excellent, line-by-line trace of a very similar example. It will allow you to visualize the call stack and the state of each execution context.
Your task is to follow the entire execution flow. Start at the section "A Practical Example with Code" to understand the initial setup in the Global Execution Context. Then, carefully trace the creation of each new function context as it's pushed onto the call stack: one() is called, creating its FEC. two() is called from within one(), creating another FEC on top. three() is called from within two(), adding a third FEC to the stack. Finally, see how the stack unwinds as each function completes in the section "The Function Returns and Exits the Stack". Note: The article mentions let, const, and the "Temporal Dead Zone (TDZ)". This is a preview of our next lesson. For now, just focus on how var is handled and how the contexts are created and removed from the stack.
Seeing it Live: The Developer Tools
Reading about the process is one thing; seeing it happen live is another. As a software engineer, your browser's developer tools are your best friend for understanding and debugging code. We can use the debugger to pause execution and inspect the call stack and the variables within each scope, just like in the walkthrough you just read.
JavaScript Under The Hood [2] - Execution Context
In this video, Brad Traversy provides a practical demonstration of exactly what we've been discussing. Watching this will connect the theory directly to the tools you use every day.
Watch the segment from live debugger demo. As he steps through the code with a breakpoint: Notice the Scope panel. Before a line is executed, you'll see variables listed as undefined (the Creation Phase). After the line executes, they get their values (the Execution Phase). Watch the Call Stack panel. You'll see getSum appear on top of the stack when it's invoked and disappear when it returns. This is the LIFO principle in action.
This practical demonstration reinforces the entire model. The "magic" of JavaScript execution becomes a predictable, traceable process that you can observe and manipulate.
Conclusion
In this lesson, we dissected the process that occurs every time a function is called. You've learned how the JavaScript engine uses Execution Contexts, managed by the call stack, to run your code in a structured way.
Key Takeaways:
- Every function call creates a new Function Execution Context (FEC), which is pushed onto the call stack.
- Each execution context is processed in two phases:
- Creation Phase: The engine allocates memory for variables and functions.
varvariables are initialized toundefined, and function declarations are stored completely. - Execution Phase: The engine executes the code line-by-line, assigning values to variables and calling other functions.
- Creation Phase: The engine allocates memory for variables and functions.
- When a function returns, its FEC is popped off the call stack, and control returns to the context below it.
This two-phase mechanism is the direct cause of a behavior called hoisting. In our next lesson, we will dive deep into hoisting and use our new understanding of execution contexts to predict its behavior and see how let and const differ from var in this regard.