Skip to main content

Command Palette

Search for a command to run...

JavaScript's Thread of Execution - How Code Really Runs

Updated
5 min read

Part 1 of the JavaScript Deep Dive Series

Welcome to JavaScript Deep Dive - a comprehensive series where we'll journey through JavaScript's inner workings, one concept at a time. Over the next several articles, we'll explore everything from basic execution to advanced patterns like closures, promises, and object-oriented programming.

What we'll cover in this series:

  • Execution & Memory - How JavaScript reads and stores your code

  • Functions & Execution Contexts - The foundation of JavaScript behavior

  • Call Stack Fundamentals - Tracking function calls and nested execution

  • Stack Overflow & Limits - Understanding JavaScript's boundaries

  • Closures & Higher-Order Functions - The DRY principle in action

  • Promises & Async Patterns - Managing asynchronous operations

  • Event Loop - How JavaScript handles non-blocking operations

  • Object-Oriented Programming - The new keyword and beyond

  • The this Keyword - Context and binding demystified

  • Modern Classes - ES6+ OOP patterns

JavaScript's Sequential Nature

JavaScript operates on a simple principle: one thing happens at a time. Understanding this core concept is essential for writing predictable, debuggable code.

Line-by-Line Execution

JavaScript reads and executes code line by line, in order. When you write a program, JavaScript starts at the top and works its way down, executing each statement before moving to the next.

console.log("First");    // Executes first
console.log("Second");   // Executes second  
console.log("Third");    // Executes third
// Output: First, Second, Third

This sequential execution means that the order you write code matters. Unlike human reading where you might skim or jump around, JavaScript is (and will be) methodical and predictable (in practice).

The Single-Threaded Reality

JavaScript is fundamentally single-threaded (read more about threading here), meaning it can only execute one command at a time. There's no parallel processing happening - each line must complete before the next begins.

This has profound implications:

  • Blocking operations stop everything else from running

  • User interfaces can freeze if code takes too long

  • Predictability is high - you know exactly what order things happen

Memory Storage During Execution

As JavaScript executes code, it stores data in global memory (also called the variable environment). When you declare variables, JavaScript creates space for them and tracks their values.

const num = 3;        // Creates 'num' in memory, stores 3
const string = "hello"; // Creates 'string' in memory, stores "hello"  
let result;           // Creates 'result' in memory, initially undefined in value

Variable Hoisting

JavaScript actually scans through your code before executing it, setting up memory space for variables and functions. This is called hoisting.

javascript

console.log(myVar); // undefined (not an error!)
var myVar = "Hello World";
console.log(myVar); // "Hello World"

What actually happens:

  1. JavaScript creates myVar in memory during setup phase

  2. myVar initially gets the value undefined

  3. First console.log prints undefined

  4. Assignment happens: myVar = "Hello World"

  5. Second console.log prints "Hello World"

Tracing Execution Step by Step

const num = 3;
const string = "hello";
let result;

// Trace through execution step by step
console.log("Step 1");
result = num + 5;
console.log("Step 2");
console.log(result);

Execution order:

  1. Setup Phase (before any code runs):

    • Create num in memory

    • Create string in memory

    • Create result in memory, value undefined

  2. Execution Phase (line by line):

    • Line 1: Assign 3 to num

    • Line 2: Assign "hello" to string

    • Line 3: result stays undefined (no assignment yet)

    • Line 5: Execute console.log("Step 1") → outputs "Step 1"

    • Line 6: Calculate num + 5 (3 + 5 = 8), assign to result

    • Line 7: Execute console.log("Step 2") → outputs "Step 2"

    • Line 8: Execute console.log(result) → outputs 8

Common Pitfalls and Misconceptions

"JavaScript runs multiple things at once"

False. JavaScript is strictly single-threaded for code execution. Even asynchronous operations follow specific rules we'll cover in later articles.

"Variables exist before they're declared"

Partially true due to hoisting, but they're undefined until assignment. Understanding the difference between declaration and assignment is crucial.

"Execution order doesn't matter"

False. Order is critical for correct runtime behavior. This becomes even more important with functions and scope.

"Memory management is completely automatic"

Mostly true, but understanding when and how JavaScript manages memory helps you write more efficient code and avoid memory leaks.

Practical Applications: Better Debugging

Understanding execution flow transforms how you debug:

Reading Error Messages

When you see an error like "Cannot read property 'x' of undefined", you can trace back through execution to find exactly when and why a variable became undefined.

Predicting Program Behavior

Before running code, you can mentally trace through the execution steps and predict the output. This skill is invaluable for both development and interviews.

Identifying Performance Issues

When you understand that JavaScript can only do one thing at a time, you start thinking about which operations might block the user interface and how to structure code for better performance.

Summary: Your Mental Execution Model

The key takeaway is developing a mental model of JavaScript as a methodical, step-by-step executor:

  1. Setup Phase: JavaScript scans code and sets up memory space

  2. Execution Phase: Code runs line by line, in order

  3. Memory Management: Variables are stored and tracked throughout

  4. Single-threaded: Only one operation at a time

This foundation is crucial for understanding more complex concepts like:

  • How functions create their own execution contexts

  • Why closures work the way they do

  • How asynchronous operations fit into single-threaded execution

  • Object creation and the this keyword

Next up: We'll explore how functions create their own execution contexts and why understanding this concept is the key to mastering JavaScript scope, closures, and advanced patterns.

Javascript Deep dive

Part 4 of 4

A journey through JavaScript's inner workings, one concept at a time. This series goes beyond syntax and into the heart of how JavaScript actually works. We'll explore the engine, the call stack, memory management, and other advanced concepts.

Start from the beginning

Maybe You Only Need Vanilla JavaScript: Challenging the Framework-First Mindset

Have you ever reached for create-react-app to build a simple counter? Or spun up Next.js for a page with three buttons? If you're nodding your head, you're not alone. Somewhere between 2015 and now, we collectively decided that frameworks aren't just...

More from this blog

C

Cracked Chefs by Oluwaferanmi Adeniji

19 posts

Battle-tested Coding patterns, Javascript wizardry, System Design, Product Engineering and Management, and architectural secrets.