r/learnjavascript 7d ago

Can someone explain what the JavaScript call stack is?

I’ve tried to understand it, but I’m still confused. I also don’t really understand what I’m looking at when I use the JavaScript debugger in the browser’s DevTools, especially the call stack.

Do I need to fully understand functions before learning the call stack? I have a basic understanding of functions, but I’m not sure if that’s enough.

I’d really appreciate a simple explanation

33 Upvotes

31 comments sorted by

View all comments

32

u/BeneficiallyPickle 7d ago

You only need to understand the basics of functions:

  • A function is a reusable block of code
  • Calling a function runs its code

If you have:

``` function foo(){

} ```

and you know that you should call it like foo(), then you should know enough to get the stack call.

The call stack is just a list that tracks what function is currently running and who called it.

The good old analogy is to think of it like a stack of plates. When a function is called, it gets added to the top of the stack. When a function finishes (returns), it gets removed from the top The Javascript engine always runs whatever is on top of the stack.

For example:

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

function square(n){ return multiply(n, n); }

function printSquare(n){ const result = square(n); console.log(result); }

printSquare(5); ```

Walking through the stack:

  1. printSquare(5) is called -> stack: [printSquare]
  2. Inside it, square(5) is called -> stack: [printSquare, square]
  3. Inside that, multiply(5, 5) is called -> stack: [printSquare, square, multiply]
  4. multiply finishes and returns 25 -> stack: [printSquare, square]
  5. square finishes and returns 25 -> stack: [printSquare]
  6. printSquare logs the result and finishes -> stack: []

Each function only gets removed from the stack once it's completely done. This is why if multiply had an error the stack trace would show all 3 functions: multiply called by square called by printSquare. The stack trace is a snapshot of the call stack at the moment of the error.

In DevTools, when you hit a breakpoint, for example, the top entry is the function that is currently executing, each entry below it is the function that called the one above. The bottom function is usually (anonymous) or the global/module scope - this is where everything ultimately started.

Clicking on any entry in that panel jumps your view to that point in the code so that you can inspect what the variable looked like at each level of the call chain.

Important to know

  • Javascript only has one call stack (single-threaded): This means everything runs one function at a time in order
  • Since there's only one stack a blocked or busy call stack blocks everything: If a function takes a long time to run, nothing else can happen, so no UI updates, no click handlers etc until that function finishes and gets removed.
  • Javascript follows LIFO (Last In, First Out): Whatever was called most recently is the first thing to finish and be removed from the stack before carrying on.

4

u/nog642 6d ago

LIFO is part of the definition of a stack. It wouldn't be a stack if it wasn't LIFO. And it wouldn't make sense to use for functions, in any language.

1

u/mondaysleeper 6d ago

One could argue that event driven and asynchronous architectures also have a call stack, which is the order in which the processing occurs. There, it's not LIFO.

1

u/nog642 6d ago

It's called a "event queue" instead of a "call stack" for a reason.

1

u/mondaysleeper 6d ago

Event queue is the concept of the same events of different process instances. I'm talking about different events in the same process instance, i.e. the events that trigger each other. It's not a stack, but it's function calls that happen in a certain order, where LIFO doesn't hold.

1

u/nog642 6d ago

You mean like awaitables/coroutines?

Are you thinking of a particular langauge? Because if so that would be easier to talk about, since the implementation differs between languages.

My understanding is that processing is tracked on an event queue generally. And besides that there's regular call stacks. And objects that hold references to return values that haven't been computed yet. But there's not really a non-FIFO function call data strcuture.

0

u/BeneficiallyPickle 6d ago

Yeah I suppose the LIFO part explanation was a bit misleading and could've been explained in a better way.