DEV Community

Cover image for JS Concepts: Call Stack
Mateusz Janusz
Mateusz Janusz

Posted on • Edited on

JS Concepts: Call Stack

This article is a part of a series covering fundamentals of the JavaScript language. The intention of this series is to help developers advance their knowledge and really understand how the JavaScript language works. And to help myself get better at writing 😉


Today, we're going to find out what is a call stack and how does it work in JavaScript. Let's begin! 👏

What is a call stack

We can say that the call stack is a kind of a to-do list of function invocations. It is a structure that stores a list of functions to be called.

The reason why we call it a call stack is because it stores data in a stack. Stack is an abstract data type where elements are inserted and removed according to the Last-In First-Out (LIFO) principle.

It's like a stack of pancakes; you always add to the top of the stack and remove from the top of the stack

how the stack works

Because JavaScript is mainly single threaded, it can only execute one line of code at any given time. Basically, it can only do one thing at a time.

If in a JavaScript application, you call a function, that function may resolve in any other function calls. Those functions may be waiting on results of other calls before the main function finishes. So the application needs to keep track of things that were invoked and things that are waiting to be returned. It needs to keep a history of functions that were invoked but are not done yet.

How does it work

Whenever you call a function, the details of the call are saved on top of the stack. Whenever a function returns, the information is taken off the top of the stack.

The code execution is synchronous. Whenever JavaScript engine finds a function invocation, it creates a new execution context for that function and pushes it to the top of the stack. The call stack knows the next function to be executed and will remove it after execution. It reaches to the context below it in the current stack until the memory is clear.

Let's look at the example:

function foo() {
    console.log('Hello')
}

function bar() {
    foo()
    console.log('World')
}

bar()
Enter fullscreen mode Exit fullscreen mode

This is what happens if you run this code:

  • function bar() is called; empty stack frame (execution context) is created;

Call Stack:
bar()

  • function bar() calls function foo() which is added to the top of the stack

Call Stack:
foo()
bar()

  • function foo() returns and prints 'Hello' to the console
  • function foo() is removed from top of the stack

Call Stack:
foo()
bar()

  • now, function bar() is executed and it returns, 'World' is printed to the console
  • function bar() is popped off the stack

Call Stack:
bar()

  • we ended up with an empty stack, the memory is cleared

Call Stack:
EMPTY

You can also observe this if your browser throws an error stack trace in the console. It indicates where in the function it failed. Executed functions are presented from top to bottom, like in the stack. See the example below.

Error stack trace

Stack overflow

We've all been there... This happens when we run an infinite loop.

A function invocated recursively (a function calls itself) can hit a limit on the size of the stack in a browser. That's what we call stack overflow. If this happens, a browser will stop all calls and throw 'Maximum call stack size exceeded' error.

RangeError: maximum call stack exceeded

Summary

Call stack is an ordered set of stack frames where:

  • most recently executed function is at the top of the stack
  • the first invoked function is at the bottom of the stack
  • the stack is processed from top to bottom

Other takeaways are:

  • JavaScript is single threaded, it can only do one thing at a time
  • Stack is a data structure where you always add to the top of the stack and remove from the top of the stack (LIFO)
  • Function execution is synchronous





This article was originally published on my personal blog.

Top comments (0)