Understanding Javascript Execution Context, Call Stack and Stack Overflow

Understanding Javascript Execution Context, Call Stack and Stack Overflow

JavaScript is weird. It is possible to use JavaScript without fully understanding JavaScript , and most times JavaScript lets you get away with it. If you are an aspiring JavaScript ninja like me, then you will definitely want to understand JavaScript . This will help you debug your code better and understand how your code works.

In this post, I present an awesomely simple explanation of the JavaScript Execution Context and the Call Stack. By the end of this post, you will have a mental model that helps you understand these concepts.

Give me Context

Break-Up-PNG-Free-Download.png

I remember seeing a movie where a young lover boy was to have a date with his girlfriend in a coffee shop. While he was waiting for her, a beautiful waitress came by.

The waitress seeing that the young boy's shirt collar was rough bent over, wrapping her hand around his neck to help him straighten up his collar. Just at that moment, the young boy's girlfriend walked in and saw the waitress hands around her lover and thought she was kissing him! She walked out of the coffee shop and later, walked out of the young lover's life.

You might conclude that the young man's lover had trust issues and what she saw deceived her. To state the situation correctly, she took things out of context.

The JavaScript execution context

Suppose you have the following JavaScript code:

function first() {
    second();
}
function second() {
    third();
}

function third() {
    console.log('I am the third function')
}

function boss() {
    first(); 
}

// call the boss function
boss()

Calling the boss function will execute the first() function which executes second(), which executes the third() function. At each point of execution, the JavaScript engine must be able to tell which function it is currently executing. It must know the current context of execution.

JavaScript does this by creating what is known as an Execution Context each time a funtion is executed. The execution context is an internal JavaScript concept that the JavaScript engine uses to track the execution of code.

Imagine the JavaScript engine asking itself: Which code am I currently executing? The execution context answers that.

The Global Context

Now you know that when functions are invoked, the JavaScript engine creates an execution context for them - which lets the engine know which function it is currently executing. How does the engine know if the code it's executing presently is not in a function, that is, how does it know global code? (just think of Global code has code that is not in a function.)

There are two types of context in JavaScript : the function context and the Global Context. Code executing in the global scope, not inside of a function, are placed in the global context. The global context is usually denoted as main and it is usually the first to be created.

The Call Stack

"So the last shall be first, and the first last..." - Matthew 20:16

Creating an execution context for each function invocation alone does not totally answer the question, 'which code am I currently executing?'. The JavaScript engine must be able to organize the execution contexts for every function call in a way that makes it easier for it to know the order of execution - which one comes first.

In the example above, when the boss function is executed, this is what happens:

boss -> first -> second -> third

The function invocation must then 'unfold', this means that the execution of third function will complete first, then the exection of second completes, then first completes and then the execution boss function completes.

Even though the boss method was invoked first, it completed last. The executions of the function follows a first in, last out approach.

You can imagine that function execution contexts are stacked one on top of the other in the order in which they were created. So that the first one is at the bottom and the last one is at the top. (Remember that the global context has to be created first.)

insertion.PNG

Then the completion of execution of the functions start from the top - when a function completes, it is 'removed' from the top and the one below it is executed. This continues until the call stack is empty! The first has truly become the last!

popping.PNG

The JavaScript Engine creates a stack data structure where function execution contexts are placed on creation - when the function is called or invoked. This data structure is called the Call Stack. Putting execution context in the call stack is called insertion while removal is called popping.

When the call stack is empty, the JavaScript engine knows it is done with code execution.

What is a Stack Overflow?

The call stack as implemented in JavaScript Engines is not infinite in size, it has a limit and can be exceeded by bad code. Consider the following:

function foo() {
    foo();
}

foo();

The function foo calls itself and then calls itself again with no condition for stopping, so we have an infinite loop of function calls. If you execute this code in a browser, the browser will throw an error telling you that you have exceeded the size of the call stack. When this happens, we say the stack has overflowed aka stack overflow.

call stack exceeded.PNG Testing the code in Brave Browser

Conceptually, this is what happened in the call stack: stack overflow.png

Aha! That is it, JavaScript Execution Context, Call Stack and Stack Overflow demystified!

Closing rant

Thanks for reading this far! I bet it's worth it. If you enjoyed reading this post as much as I enjoyed writing it, (typing it...right? :) ) please share on social media, you can follow me on twitter @solathecoder .

Happy Hacking!