JavaScript is:
- Single-threaded → Only one command is executed at a time.
- Synchronous by default → Code runs line-by-line, unless asynchronous features (promises, setTimeout, async/await) are used.
- Interpreted / Just-in-Time Compiled → The JS engine parses and executes code quickly.
Execution happens inside a JavaScript engine (like Chrome's V8 or Node.js's V8-based engine), which has two main parts:
- Memory Heap – Stores variables and function definitions.
- Call Stack – Keeps track of what function is currently running.
Think of Execution Context (EC) as the environment in which JavaScript code is evaluated and executed. It determines:
- Which variables can be accessed
- The value of
this - How functions run and interact
- Created when the script starts running.
- Creates a global object (
windowin browsers,globalin Node.js). - Sets
thisto the global object (in non-strict mode). - Only one GEC exists at any time.
- Created whenever a function is invoked.
- Each function call gets its own context.
- Has access to:
- Its own variables
- Outer variables (via scope chain)
- Global variables
- Created by code inside
eval()(rarely used in modern development).
Each EC is created in two phases:
- Scope Chain is established.
- Variables & functions are hoisted:
- Variables declared with
varare initialized toundefined. - Functions are fully hoisted with their definitions.
- Variables declared with
thisvalue is determined.
- Code is executed line by line.
- Variable values are assigned.
- Functions are invoked (which may create new FECs).
JavaScript keeps track of execution contexts using the call stack.
- Global Execution Context is at the bottom.
- When a function is called → a new Function Execution Context is pushed onto the stack.
- When the function finishes → its EC is popped off the stack.
function first() {
console.log('First');
second();
}
function second() {
console.log('Second');
}
first();- Push GEC → run script
first()called → push first FECsecond()called inside → push second FECsecondfinishes → popfirstfinishes → pop- GEC finishes → stack empty
Here's the mental model you can present in an interview:
"JavaScript runs in a single-threaded environment with a call stack and a memory heap. The code is executed inside an execution context, which provides the scope, variables, and value of this. When the script starts, the Global Execution Context is created, followed by Function Execution Contexts whenever functions are invoked. Execution contexts are managed in the call stack, with the creation and execution phases handling hoisting and code execution respectively."
[Memory Heap] [Call Stack]
┌─────────────┐ ┌───────────────┐
│ Variables │ │ second() │ ← top
│ Functions │ │ first() │
└─────────────┘ │ GEC │ ← bottom
└───────────────┘