DEV Community

Cover image for How JavaScript Executes Code: A Step-by-Step Breakdown of Program Execution
gautam kumar
gautam kumar

Posted on

How JavaScript Executes Code: A Step-by-Step Breakdown of Program Execution

JavaScript is a high-level, interpreted, and just-in-time (JIT) compiled programming language that follows a process to execute code in a structured way. Understanding how JavaScript executes a program helps in writing efficient code and avoiding potential issues.

JavaScript Execution Flow Overview

When you write JavaScript code, the JavaScript engine (e.g., V8 for Chrome and Node.js, SpiderMonkey for Firefox) processes it in multiple steps:

  1. Parsing (Syntax Analysis)
  2. Early Error Checking
  3. Compilation (JIT Compilation)
  4. Execution (Execution Context Creation and Code Execution)

Step-by-Step Execution Process

Step 1: Parsing (Syntax Analysis)

  • The first thing the JavaScript engine does is parse the code.
  • It breaks the source code into tokens (small meaningful units like keywords, identifiers, etc.).
  • A syntax tree (AST - Abstract Syntax Tree) is generated from these tokens.
  • If the syntax is incorrect, an early error occurs, and execution is stopped.

Example: Syntax Error

console.log("Hello, World");
console.log("test line) // Missing quotes or closing parenthesis
console.log("last line")
Enter fullscreen mode Exit fullscreen mode

If the engine finds a syntax error during parsing, the script will not run.

Step 2: Early Error Checking

  • Before execution, JavaScript performs early error checking, such as:
    • Variable declarations and re-declarations.
    • Reserved keyword usage.
    • Block scoping violations (e.g., using let variables before declaration).
    • Incorrect function calls.

Example: Early Error Checking

let x = 5;
let x = 10;  // Early error: 'x' has already been declared
const y;    // Missing initializer in const declaration
Enter fullscreen mode Exit fullscreen mode

If an early error is detected, execution is stopped immediately, and an error is thrown.

Step 3: Compilation (JIT Compilation)

JavaScript is not purely interpreted language. Modern engines like V8 (Chrome, Node.js) and SpiderMonkey (Firefox) use Just-In-Time (JIT) Compilation to optimize code execution.

The compilation happens in two stages:

  1. Interpreter (Baseline Compiler)
    • Quickly converts code into machine code for fast startup.
  2. Optimizer (JIT Compiler)
    • Analyzes repeated code patterns and optimizes them for performance.

Thus, JavaScript has a mix of interpreted and compiled behavior, improving speed.

Step 4: Execution (Execution Context Creation and Code Execution)

Before running the program, JavaScript prepares the environment by setting up Execution Contexts, where each script runs inside a Global Execution Context (GEC).

Execution Context Creation Steps:

  1. Creation Phase:

    • The global execution context is created.
    • The this keyword is assigned a value (e.g., window in the browser, global in Node.js) in the GEC (global execution context)
    • Memory is allocated for variables and functions (but they are not executed yet).

    Define Scope Before Execution

    Before the code runs, JavaScript sets up the scope of variables, which determines their visibility and accessibility. This happens in the creation phase of the execution context.

    Variables declared with var are hoisted to the top of their scope and initialized with undefined.

    Variables declared with let and const are hoisted but not initialized (this results in a Temporal Dead Zone (TDZ) error if accessed before declaration).

    Example: Variable Hoisting

    console.log(a); // undefined (due to hoisting with `var`)
    var a = 10;
    
    console.log(b); // ReferenceError (due to temporal dead zone)
    let b = 20;
    
  2. Execution Phase:

    • The code is executed line by line.
    • Variables and function calls are resolved.
    • The call stack is used to track execution.

    Understanding Call Stack in Execution

    JavaScript has a single-threaded execution model, meaning it can execute one command at a time using the Call Stack.

    When a function is called, it gets pushed onto the stack.

    When it completes execution, it is popped from the stack.

    Example: Call Stack

    function greet() {
      console.log("Hello");
    }
    
    function sayGoodbye() {
      console.log("Goodbye");
    }
    
    greet();
    sayGoodbye();
    

    Execution order in the call stack:

    1. greet() → Push to stack → Execute → Pop
    2. sayGoodbye() → Push to stack → Execute → Pop

Example: Putting It All Together

Let's consider a simple code snippet and understand how it runs:

console.log("Start");

function multiply(a, b) {
  return a * b;
}

let result = multiply(2, 3);

console.log("Result:", result);
console.log("End");
Enter fullscreen mode Exit fullscreen mode

Execution Steps:

  1. Parsing: No syntax errors, move to the next step.
  2. Early Error Checking: No variable scope or redeclaration issues.
  3. Compilation: Functions and variables are set in memory.
  4. Execution:
    • "Start" is printed.
    • multiply(2, 3) is called.
    • "Result: 6" is printed.
    • "End" is printed.

Key Takeaways

Execution Phases:

  • JavaScript code goes through parsing, compilation, and execution.
  • Early error checking prevents runtime crashes.

Scope Handling:

  • Variables are hoisted before execution.
  • var vs. let/const differences affect how the code behaves.

Efficient Execution:

  • JavaScript's JIT compilation speeds up repeated operations.
  • Call stack manages function execution order.

Summary

Phase Description
Parsing Code is broken into tokens and checked for syntax
Early Error Check Detects issues like re-declarations and scoping
Compilation JIT compiles code for optimized performance
Execution Code runs in an execution context

Top comments (0)