Mastering Modern JavaScript Applications
Execution Contexts
The Execution Context
Every line of JavaScript you write runs inside an environment called an Execution Context. Think of it as a wrapper for your code, containing everything needed for it to be executed. When your script first runs, the JavaScript engine creates a Global Execution Context. This is the base level, the default environment for any code that isn't inside a function.
Every line of JavaScript runs inside an Execution Context — this is the foundation of how JS works.
When a function is called, a new, separate environment is created just for that function. This is a Function Execution Context. Since you can have many functions, and functions can call other functions, you can have many Function Execution Contexts. The engine needs a way to manage all of them.
The Two Phases of Execution
Before the JavaScript engine executes your code line-by-line, it first does a quick scan. This process happens in two distinct phases for every execution context.
Memory Creation Phase: The engine allocates memory for all variables and functions defined within the context. For variables declared with
var, it assigns a placeholder value ofundefined. For function declarations, it stores the entire function code in memory. This is why you can call a function before its physical declaration in the code, a behaviour known as hoisting.Code Execution Phase: After setting up memory, the engine executes the code line by line. It assigns the actual values to variables and runs the logic inside functions.
Let's look at a simple example:
console.log(myVar); // logs 'undefined'
var myVar = 10;
console.log(myVar); // logs 10
myFunction(); // logs "Hello!"
function myFunction() {
console.log("Hello!");
}
In the Memory Creation Phase for the Global Execution Context:
- Memory is allocated for
myVarand it's initialized toundefined. - Memory is allocated for
myFunction, and the entire function's code is stored.
In the Code Execution Phase:
console.log(myVar)runs. The engine findsmyVarin memory and sees its value isundefined.- The line
myVar = 10is executed, and the value ofmyVarin memory is updated to10. console.log(myVar)runs again, this time logging10.myFunction()is called. The engine finds it in memory and executes its code.
The Call Stack
So how does the JavaScript engine keep track of which execution context is currently running, especially when functions call other functions? It uses a mechanism called the Call Stack.
The Call Stack is a data structure that operates on the Last-In, First-Out (LIFO) principle. The last context that gets pushed onto the stack is the first one to be popped off.
Here’s how it works:
- When the script starts, the Global Execution Context is created and pushed onto the call stack.
- If a function
first()is called, a new Function Execution Context forfirst()is created and pushed on top of the Global context. - If
first()then calls another function,second(), an execution context forsecond()is created and pushed on top offirst()'s context. - The engine always executes the context at the top of the stack. So, it runs the code in
second(). - Once
second()finishes, its context is popped off the stack. Control returns tofirst()'s context, which is now at the top. - When
first()finishes, it too is popped off. Control returns to the Global Execution Context. - When the entire script is finished, the Global Execution Context is popped off, and the stack is empty.
This orderly, single-file process is what makes JavaScript a single-threaded language. It can only execute one piece of code at a time, corresponding to the single execution context at the top of its one and only call stack.
What is the very first execution context created when a JavaScript script begins to run?
An execution context is created in two phases. What happens during the first phase, the Memory Creation Phase?
Understanding the execution context and the call stack is fundamental. It clarifies how the JavaScript engine interprets and runs your code, explaining concepts like hoisting and the single-threaded nature of the language from the ground up.