Understanding Execution Context in JavaScript: A Complete Guide with Examples & Call Stack Insights


JavaScript Execution Context
An execution context is the internal environment in which JavaScript code is evaluated and executed. In simpler terms, it’s like a container or box that holds everything the engine needs to run a piece of code. The ECMAScript spec describes it as a mechanism to track runtime evaluation of code. In practice, an execution context includes the current code to execute, its scope and variables, and the value of this
. For example, one expert explains that in layman’s terms an execution context “roughly equates to the environment a function executes in: variable scope (and scope chain), function arguments, and the value of this
”.
Creation and Lifecycle
JavaScript creates a global execution context when a script first starts. This happens even if your code is empty – the engine always makes one global context. The creation process has two phases:
Creation Phase: The engine scans the code and allocates memory. It sets up the Global Object (in browsers,
window
) and thethis
binding (initially pointing to the global object). All declared variables and functions are placed into memory: functions are stored and variable names exist with the valueundefined
.Execution Phase: The code runs line by line. Variables are assigned real values and functions may be invoked. When a function is called, a new function execution context is created on top of the stack (see Call Stack below).
Figure: Example Global Execution Context at creation phase (memory view). When a script loads, the engine builds the Global Execution Context. In the creation phase, it allocates space for all top-level variables and functions (initially undefined
) and establishes the global object and this
binding. In the illustration above (from a simple example), variables a
, sum1
, and sum2
exist but are undefined
, while the function add
is registered in memory. In the subsequent execution phase, the engine will assign actual values (e.g. a=20
) and run code.
Every time a function is invoked, the engine creates a new Function Execution Context. That function’s context also has a creation phase (allocating space for its local variables and parameters) and an execution phase (running the function body). After the function finishes (hits return
or ends), its context is popped off the stack (destroying its local environment) and control returns to the previous context.
Types of Execution Contexts
JavaScript defines three main execution context types:
Global Execution Context (GEC): This is the base context for any script. There is exactly one global context per program (per JavaScript realm). It contains all global variables and functions, plus the global object (
window
orglobal
) and the initialthis
value (which is the global object in non-strict mode).Function Execution Context: Created whenever a function is called. Each call to a function – even recursive calls – gets its own execution context on the stack. The function’s local variables, parameters, and inner functions reside in this context. The value of
this
inside the context depends on how the function is called (e.g. method call,new
, or default global).Eval Execution Context: Rarely used, this is created when code is run via
eval()
. It behaves much like a function context but executes string code in its own environment. (Becauseeval
is discouraged for security reasons, it’s uncommon in practice.).
(Some sources also mention a fourth type for ES6 modules, but for traditional scripts the above three cover most cases.)
Contents of an Execution Context
Each execution context is essentially a set of data structures holding the environment for code execution. Key components include:
Lexical Environment: An object that holds the current scope’s variables and their values. It includes an environment record (mapping names to values) and a reference to an outer (parent) lexical environment. The scope chain is formed by linking these environments from inner to outer, so a function can access variables in its enclosing scopes. For the global context, the outer reference is
null
.Variable Environment: Similar to the lexical environment but specifically holds
var
declarations. In modern implementations, lexical and variable environments are often the same object at first. They track function declarations, variables, and in ES6,let
/const
and class bindings in that context.this
Binding: Each context fixes the value ofthis
inside that environment. In the Global Context,this
is the global object. In a Function Context,this
may be the global object (if the function is called normally),undefined
(in strict mode), or some specific object if the function was called as a method or withcall
/apply
.Arguments Object: In a function context, there is also an
arguments
object that holds the passed parameters.Code and Execution State: Internally, the context keeps track of where in the code it is (especially important for features like generators or async). But for learning purposes, you mainly need to know that all the function’s local data lives here.
MDN summarizes the bindings tracked: “execution context tracks… variables defined with var
, let
, const
, function
, class
, etc., and the this
reference”. In other words, all names (identifiers) available in that context, plus this
, are recorded.
Call Stack and Context Management
JavaScript uses a call stack (execution stack) to manage execution contexts. This is a LIFO (Last-In-First-Out) stack where the global context starts at the bottom. When a script runs, its global context is pushed first. When a function call occurs, the engine creates a new context for that function and pushes it onto the top of the stack. That new context becomes the running context. When the function returns, its context is popped off the stack and the previous context resumes as the running context.
For example, consider this code:
function foo(x) {
const y = 10;
return x + y;
}
function bar(z) {
return foo(z * 2);
}
const result = bar(5);
console.log(result);
Global Context: The engine starts by creating the global context. It sees
foo
,bar
, andresult
declared. Initially,result
isundefined
.Call
bar(5)
: A new Function Context forbar
is created and pushed onto the stack. In this context,z
is5
.Inside
bar
, callfoo(z*2)
: Evaluatez * 2
(10
), then push a new Function Context forfoo
. Now the stack has Global → bar → foo. In thefoo
context,x=10
.Execute
foo
: Insidefoo
, it computesy = 10
(local), then returnsx + y = 20
. Thefoo
context is then popped off the stack. Control returns tobar
.Return to
bar
: The call tofoo
gave20
.bar
returns that value. Thebar
context is popped off the stack.Back to Global: The return value (20) is assigned to
result
, andconsole.log(result)
runs in the global context. Once the script ends, the global context is popped as well (call stack is empty), and execution finishes.
MDN describes this stacking process step by step. The key idea: the call stack holds all active execution contexts, and only the top context is currently running.
Real-World Analogy
One way to picture this is a stack of plates in a cafeteria:
Each plate = an execution context: Each function call gets its own “plate” (context) with its own data (variables, parameters).
Putting a plate on top = calling a function: When a function is invoked, put a new plate on the stack.
Taking a plate off = finishing a function: When the function returns, remove (pop) that top plate, revealing the one beneath (the caller’s context).
The global context is the bottom plate (and never removed until the program ends). Inside each “plate” (context), you have all the ingredients (variables, scope) needed for that function to run.
Example Walkthrough
Consider this concrete example to see contexts in action:
var x = 2;
function add(y) {
var z = x + y;
return z;
}
var result = add(3);
console.log(result);
Global Creation: Global context is created. Variables
x
,add
, andresult
are hoisted. Initiallyx=undefined
,add
is the function, andresult=undefined
(before execution).Global Execution: The engine runs the code: assigns
x = 2
. Now the global context hasx=2
, and the functionadd
ready.Function Call (
add(3)
): A new context foradd
is created on the stack. In this context, the parametery
is3
and a localz
is prepared (initiallyundefined
). Theadd
context also has access to the outer (global) lexical environment, so it can seex=2
.add
Execution: Insideadd
, computez = x + y = 2 + 3 = 5
. Thenreturn z
(value5
).Return from
add
: Theadd
context is popped off the stack. Control goes back to the global context, and the returned value5
is assigned toresult
.Global Continues: Now
result = 5
. The engine executesconsole.log(result)
, outputting5
. After this, the script ends, and the global context is popped off the stack.
Throughout this process, you can trace which context is running and what each contains. For example, when inside add
, the local variables are y=3
and z=5
, and x
comes from the global lexical environment. The scope chain ensures add
finds x
in the outer context.
Summary
Execution Context: A container/environment that holds the information needed to run code (scope, variables,
this
).Creation: Global context is created at program start (phase 1: allocate, phase 2: run). Each function call creates a new context.
Types: Global, Function, and Eval contexts.
Contents: Each context includes a Lexical Environment (scope with variable bindings) and
this
binding (plus arguments for functions).Call Stack: A LIFO stack that tracks contexts. New contexts push on top when functions run, and pop off when functions return.
Understanding execution contexts and the call stack is crucial for deeper insights into JavaScript behavior (like hoisting, closures, and this
binding).
References
ECMAScript Specification – Execution Contexts (ECMA-262)
MDN Web Docs – JavaScript execution model
Coralogix Blog – Understanding the Execution Context in JavaScript
Prototyp Blog – What is Execution Context in JavaScript
StackOverflow discussion – Execution Context vs Scope.
Subscribe to my newsletter
Read articles from ANKIT ANAND directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

ANKIT ANAND
ANKIT ANAND
👋 Hi, I'm Ankit Anand—a tech enthusiast passionate about web development, Java Full Stack, MERN Stack, and AI/ML. 🚀 Here to share my learning journey, insights, and projects as I explore and grow in the world of tech. Let's learn together! 🌱