Execution context
Understand creation, execution, lexical environments, this binding, and the call stack behind every JavaScript invocation.

WHAT YOU WILL BE ABLE TO DO
Learning outcomes
- Explain execution context in plain language.
- Connect the behavior to the underlying browser or framework model.
- Implement the core pattern and reason through edge cases.
- Answer common follow-ups without relying on memorized phrases.
01Overview
An execution context is the environment in which code runs: global context, a function context created on every call, or eval context. Each has a variable environment, a lexical environment, and a this binding.
02Mental model
Every context goes through a creation phase, where var declarations and function declarations are set up (hoisted) before any code executes, and an execution phase, where code runs top to bottom and assignments actually happen. The call stack is simply the stack of active execution contexts.
03Examples
console.log(a); // undefined, not ReferenceErrorvar a = 10;
foo();function foo() { console.log('hoisted'); }04Check understanding
Why does console.log(a) log undefined instead of throwing before var a = 10?
During the creation phase, var a is hoisted and initialized to undefined; the assignment to 10 only happens when execution reaches that line.
DDConcept deep dives
Deep dive 1
A context contains the state needed to execute code
The specification models running code with execution contexts. A context tracks structures such as the current lexical environment, variable environment, private environment, function, realm, and script or module. Interview diagrams often simplify this to variables, this, and the scope chain; useful simplification should not imply that all bindings are ordinary object properties.
- Global code, functions, and eval establish different execution circumstances.
- A lexical environment is a linked binding structure, not the same thing as the call stack.
- Modules have module environment records and do not expose top-level declarations as global properties.
Deep dive 2
Declaration instantiation happens before statement evaluation
Before a function body evaluates top to bottom, parameters and declarations are processed according to their declaration kind. Function declarations can already hold functions, var bindings begin as undefined, and lexical declarations remain uninitialized. This is the precise mechanism behind the informal word hoisting and explains why declaration kinds produce different early-access behavior.
- Creation does not mean every binding has a usable value.
- Assignment expressions still occur where they appear during evaluation.
- Parameter defaults have their own scope and evaluation rules.
Deep dive 3
The stack represents active synchronous calls
A call pushes the callee's execution context and completion removes it, returning control to the caller. Await and host callbacks do not keep ordinary frames blocked on the stack. Await suspends the async function's evaluation; a later job resumes its continuation. A timer callback is invoked in a new call after the original scheduling call has completed.
- Stack traces describe a chain of active calls, with async tooling sometimes reconstructing causal links.
- Unbounded synchronous recursion consumes stack until the engine limit is reached.
- Asynchronous recursion can avoid one continuous stack but still needs termination and resource control.
QAInterview questions and model answers
Attempt each answer aloud before opening it. The model answer shows the depth and precision expected in an interview; it is not a script to memorize.
Intermediate · Conceptual · 1 min · Question 1What is an execution context?Open model answer
Model answer
It is the runtime environment used to evaluate code, including lexical and variable environment records, the current this binding, and other execution state. Global code, function calls, and eval create contexts with different rules.
Open question page →Intermediate · Conceptual · 1 min · Question 2How is the call stack related to execution contexts?Open model answer
Model answer
Calling a function creates and pushes a new execution context. Returning or throwing removes it, resuming the caller. The stack explains synchronous control flow; asynchronous callbacks create later calls rather than leaving the original function frame suspended.
Open question page →Intermediate · Coding · 1 min · Question 3What happens before a function body executes?Open model answer
Model answer
The runtime establishes parameter bindings, local declarations, the lexical environment, and this according to the function's call form. Function declarations are initialized early; let, const, and class bindings exist but remain uninitialized until evaluation reaches them.
foo(); // "hoisted" — declaration is ready before this lineconsole.log(x); // undefined — `var x` exists, not yet assignedvar x = 10;function foo() { console.log('hoisted'); }Intermediate · Conceptual · 1 min · Question 4Are async functions kept on the call stack while awaiting?Open model answer
Model answer
No. Await evaluates its operand and suspends the async function. Its continuation is scheduled when the adopted promise settles, allowing the current stack to unwind. Local state is preserved by the async function machinery, not by blocking a stack frame.
Open question page →Intermediate · Conceptual · 1 min · Question 5What is a lexical environment record?Open model answer
Model answer
It is a specification-level structure mapping identifiers to bindings, optionally linked to an outer environment. Identifier resolution walks that chain. It is a better model than imagining variables as properties of the call stack.
Open question page →Intermediate · Coding · 1 min · Question 6How does recursion fail with a stack overflow?Open model answer
Model answer
Each unresolved synchronous recursive call consumes another stack frame. Without a base case, or with input deeper than the engine's stack capacity, the engine throws a range error. JavaScript engines are not generally required to optimize ordinary tail calls in deployed environments.
function depth(n) { return depth(n + 1); } // no base casedepth(1); // RangeError: Maximum call stack size exceededIntermediate · Conceptual · 1 min · Question 7What is the global execution context in a browser module?Open model answer
Model answer
Module code executes with module semantics and its own environment; top-level this is undefined and declarations do not become global object properties.
Open question page →Advanced · Conceptual · 1 min · Question 8How do lexical and variable environments differ?Open model answer
Model answer
They are specification components used for different declaration and scope behavior. Modern explanations should avoid assuming two permanent plain objects with every variable copied into them.
Open question page →Intermediate · Conceptual · 1 min · Question 9Does a closure keep an execution context on the call stack?Open model answer
Model answer
No. The call context can finish and leave the stack. Referenced lexical environments remain reachable through the function object without an active synchronous frame.
Open question page →Advanced · Conceptual · 1 min · Question 10What information does a realm contribute?Open model answer
Model answer
A realm groups intrinsic objects and a global environment. Values from another iframe can therefore have different intrinsic constructors, affecting checks such as instanceof.
Open question page →SCScenario questions
Scenario 1
An interviewer claims a timer callback resumes the execution context that scheduled it. Correct the model.
- Separate the original call from the host timer registration.
- Explain that the original stack unwinds normally.
- Describe the callback becoming an eligible task later.
- Explain that invoking it creates a new execution context.
Reveal worked answer
The scheduling function does not remain paused. It registers a callback with the host and returns. Once the delay and queue conditions are satisfied, the event loop selects the timer task and invokes the callback, creating a fresh function execution context on a new call stack.