Skip to content
Beginner10 min study

Execution context

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

Question progress0 / 10 completed
Start the lesson
Execution context visual explanation

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.

Think of it like this: setting up a room before a meeting starts — chairs and the projector (variable declarations) get placed in the room before anyone actually starts talking (the creation phase), and only once everyone's seated does the actual meeting, the code running line by line, begin (the execution phase).

03Examples

JavaScript
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.

How to say it out loud: "An execution context is the environment JavaScript sets up to run a piece of code — there's one for the global scope, and a new one gets created every time a function is called. Each context goes through two phases: a creation phase, where the engine sets up memory for variables and hoists declarations before anything actually runs — var gets initialized to undefined, function declarations get their full definition — and then an execution phase, where code actually runs top to bottom and real values get assigned. That's exactly why console.log(a) before var a = 10 logs undefined instead of throwing: the declaration was already hoisted and initialized to undefined during the creation phase, and the assignment just hasn't happened yet."

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.

JavaScript
foo();                       // "hoisted" — declaration is ready before this lineconsole.log(x);              // undefined — `var x` exists, not yet assignedvar x = 10;function foo() { console.log('hoisted'); }
Open question page →
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.

JavaScript
function depth(n) { return depth(n + 1); } // no base casedepth(1); // RangeError: Maximum call stack size exceeded
Open question page →
Intermediate · 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.

  1. Separate the original call from the host timer registration.
  2. Explain that the original stack unwinds normally.
  3. Describe the callback becoming an eligible task later.
  4. 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.

Verify and go deeper