No history yet

JavaScript Execution Basics

One Thing at a Time

JavaScript is often described as a single-threaded language. This sounds technical, but the idea is simple: it can only do one thing at a time.

Imagine a chef in a kitchen who can only cook one dish from start to finish before moving on to the next. They can't start boiling water for pasta while also chopping vegetables for a salad. They must complete the chopping, then move on to the boiling. JavaScript's engine, the part of the browser that runs your code, works in a similar way. It executes one line of code, then the next, in a strict order.

This single-threaded nature means JavaScript code is synchronous. One task must finish before the next one can begin.

The Call Stack

So, if JavaScript can only do one thing at a time, how does it keep track of where it is in your code, especially when functions are calling other functions?

It uses something called a call stack. Think of it like a stack of plates. When you add a new plate, you put it on top. When you take a plate away, you always take it from the top. This is known as a "Last-In, First-Out" (LIFO) principle.

In JavaScript, every time a function is called, a new "plate" representing that function is added to the top of the stack. This "plate" is called a function execution context. When the function finishes and returns a value, its plate is removed from the top of the stack. The script then resumes whatever it was doing before that function was called.

function second() {
  console.log('Hello from second!');
}

function first() {
  console.log('Calling second...');
  second();
  console.log('...second has finished.');
}

// Start of the script
console.log('Calling first...');
first();
console.log('All done!');

Let's trace how the call stack manages this code.

  1. The script begins. The call stack is empty.
  2. The first() function is called. Its execution context is pushed onto the stack.
  3. Inside first(), the second() function is called. Its execution context is pushed on top of first()'s.
  4. second() runs its console.log and finishes. Its context is popped off the stack.
  5. Execution returns to where it left off in first(). The next console.log runs, and then first() finishes. Its context is popped off the stack.
  6. The script finishes, and the call stack is empty again.

Function Execution Context

We've mentioned the "function execution context" a few times. What is it, exactly? It’s the environment a function runs in. Every time a function is called, it gets its own execution context, which is a private little workspace for that specific call.

This context contains everything the function needs to do its job, including:

  • Its local variables: Any variables declared inside the function only exist within this context.
  • A reference to any outer variables it has access to.
  • The value of this.

When the function is done, its execution context is destroyed along with all its local variables. This is why a variable created inside one function isn't accessible from another, it's neatly contained within its own workspace.

Quiz Questions 1/5

What does it mean when we describe JavaScript as a "single-threaded" language?

Quiz Questions 2/5

The JavaScript call stack operates on a "Last-In, First-Out" (LIFO) principle. What does this mean?

Understanding this single-threaded model and the call stack is the first step. It provides the foundation for how JavaScript manages its workload, one task at a time.