Call Stack in JavaScript

Call Stack in JavaScript

This article is aimed at explaining 😃 what the call stack is and why it is needed. An understanding of the call stack will give clarity to how “function hierarchy and execution order” works in the JavaScript engine.

But before we jump the gun,🤫 let us first attempt to answer the question - What is the call stack?🤠

At the most basic level, a call stack is a data structure that uses the Last In, First Out (LIFO) principle to temporarily store and manage function invocation (call).

The call stack 🏳️‍⚧️

The call stack is a mechanism JavaScript uses to keep track of functions. When you call a function JavaScript will add that function to the call stack. If this function calls another function, JavaScript will add that function to the call stack as well, above the first function.

This process will repeat with any other function that will be called by the previous function. When one function is finished, JavaScript will remove that function from the call stack. There are two important things. The first thing is that every new function in the stack will be added to the top of the call stack.

The second thing is that the call stack is executed from the top to the bottom. The last function added to the stack will be executed first. The first function added to the stack will be executed as the last. This is also called theLIFO principle (Last-In-First-Out).

Let’s illustrate this in code with one simple example.

function myFuncOne() {
  return 'This is the end.'
}

function myFuncTwo() {
  myFuncOne()

  return 'Knock knock.'
}

// Call stack is still empty here

myFuncTwo()

// Call stack:
// Step 1: myFuncTwo() is invoked
// Step 2: myFuncTwo() added to the call stack
// Step 3: myFuncTwo() calls myFuncOne()
// Step 4: myFuncOne() is added to the call stack
// Step 5: myFuncOne(), is executed
// Step 6: myFuncOne() removed from the stack
// Step 7: JavaScript goes back to myFuncTwo()
// Step 8: any code left inside myFuncTwo() after myFuncOne() call is executed
// Step 9: myFuncTwo() is removed from the stack
// Step 10: call stack is empty

How does the call stack handle function calls?🤔

We will answer this question by looking at a sample code of a function that calls another function.

Here is the example code:

function firstFunction(){
  console.log("Hello from firstFunction");
}

function secondFunction(){
  firstFunction();
  console.log("The end from secondFunction");
}
secondFunction();

oEp65Ec9CD4CnL7t0uSPoyzrkA1i1BR-Ij1n.png

This is what happens when the code is run:

  1. When secondFunction() gets executed, an empty stack frame is created. It is the main (anonymous) entry point of the program.
  2. secondFunction() then calls firstFunction()which is pushed into the stack.
  3. firstFunction() returns and prints “Hello from firstFunction” to the console.
  4. firstFunction() is pop off the stack.
  5. The execution order then move to secondFunction().
  6. secondFunction() returns and print “The end from secondFunction” to the console.
  7. secondFunction()is pop off the stack, clearing the memory.

What is LIFO?🧐

When we say that the call stack, operates by the data structure principle of Last In, First Out, it means that the last function that gets pushed into the stack is the first to pop out, when the function returns.

Let's understand what is LIFO with a simple example

As an example, consider the following program:

void bar() {
}

void foo() {
  bar();
}

int main() {
  foo();
}

When the program is run, the main() function is called, so an activation record is created and added to the top of the stack. Then main() calls foo(), which places an activation record for foo() on the top of the stack. Then bar() is called, so its activation record is put on the stack. When bar() returns, its activation record is removed from the stack. Then foo() completes, removing its activation record. Finally, the activation record for main() is destroyed when the function returns.

cs.png

In summary 😌

The key takeaways from the call stack are:

  1. It is single-threaded. Meaning it can only do one thing at a time.
  2. Code execution is synchronous.
  3. A function invocation creates a stack frame that occupies a temporary memory.
  4. It works as aLIFO — Last In, First Out data structure.

Did you find this article valuable?

Support Chhakuli Zingare by becoming a sponsor. Any amount is appreciated!