The JavaScript engine
A JavaScript engine is the program that reads your source code and executes it. The most widely known engine is V8, developed by Google and used in both Chrome and Node.js. Other engines include SpiderMonkey (Firefox) and JavaScriptCore (Safari). At a high level, the engine has two core components:- The heap — an unstructured region of memory where objects are allocated dynamically.
- The call stack — an ordered data structure that tracks which function is currently executing and where execution should return after each function completes.
- The source code is parsed into an abstract syntax tree (AST).
- An interpreter (Ignition in V8) converts the AST into bytecode and begins executing it.
- A profiler monitors which functions are called frequently (“hot” paths).
- The optimising compiler (TurboFan in V8) compiles hot functions into highly optimised machine code.
- If assumptions made during optimisation turn out to be wrong, V8 deoptimises back to interpreted bytecode.
You don’t need to manage JIT compilation manually. But knowing it exists helps explain why JavaScript performance can vary significantly between code patterns that look superficially similar.
The heap
The heap is where JavaScript allocates memory for objects, arrays, closures, and other reference types. When you write:{ name: "Alice", age: 30 } is stored on the heap. The variable user holds a reference — a pointer — to that location in memory. Primitive values like numbers, strings, and booleans are typically stored by value, either on the stack or inlined directly.
The heap is managed automatically by the garbage collector, which periodically reclaims memory that is no longer reachable. You will learn more about garbage collection in the Garbage Collection article.
The call stack
The call stack is a LIFO (last-in, first-out) data structure. Every time you call a function, a new stack frame is pushed onto the top of the stack. That frame records:- The function’s local variables and arguments.
- The return address — where execution should resume after the function finishes.
main() is pushed
The JavaScript engine starts executing the script. An implicit
main frame is placed on the stack.greet('Alice') is pushed
greet is called. A new frame for greet is pushed on top of main. Local variable name = "Alice" is recorded in this frame.buildMessage('Alice') is pushed
Inside
greet, buildMessage is called. Its frame is pushed on top. The template literal is evaluated and the string "Hello, Alice!" is produced.buildMessage returns
buildMessage finishes. Its frame is popped. Control returns to greet, which receives the return value.greet returns
greet finishes. Its frame is popped. Control returns to main with the string "Hello, Alice!".Stack overflow
Because the call stack has a fixed maximum size (typically a few thousand frames depending on the environment), deeply or infinitely recursive functions will exhaust it:The runtime
The JavaScript engine itself is deliberately minimal — it executes JS code but provides almost no I/O capabilities on its own. The runtime wraps the engine and adds the environment-specific APIs that make JavaScript practically useful. In the browser, the runtime includes:- Web APIs —
setTimeout,fetch,XMLHttpRequest, the DOM,localStorage,WebSockets, and so on. These are implemented in C++ by the browser, not by the engine. - The event queue (callback queue) — a list of callbacks waiting to run once the call stack is empty.
- The microtask queue — a higher-priority queue used for Promise callbacks and
queueMicrotask. - The event loop — the mechanism that coordinates all of the above.
fs, http, process, etc.), and uses libuv to handle asynchronous I/O instead of the browser’s event infrastructure.
Putting it all together
0, the output is:
setTimeout is a Web API call. The callback onTimeout is handed to the browser’s timer API, and even with a zero delay, it is placed into the callback queue only after the current call stack is fully empty. The event loop then picks it up. You will explore this in depth in the Event Loop article.
Summary
| Component | Role |
|---|---|
| JS Engine (V8) | Parses, compiles, and executes JavaScript |
| Heap | Allocates memory for objects and closures |
| Call stack | Tracks the current execution position (LIFO frames) |
| Web APIs | Provides browser or Node.js built-in capabilities |
| Event / task queue | Holds callbacks ready for execution |
| Event loop | Moves callbacks from queue to stack when stack is empty |