Understanding JavaScript Execution Context, Functional Execution Context, and Call Stack

Introduction

JavaScript is a synchronous single threaded language which means It can execute one task at a time in particular order, To manage this execution order and track the state of functions being called, it utilises the concepts of execution context. In this blog post we’ll deep dive into how a javascript program is executed, what is Execution context and everything that happens inside it.

Execution Context

Everything inside JS happens in the Execution Context. Execution context can be thought like a big box or environment in which JavaScript code is executed.

2 Parts of Execution Context

Whenever a javascript program runs an Execution Context is created. It is has two parts.

  1. Memory Part: Also known as Memory Creation Phase, Memory Component & Variable Environment. In this phase JS allocates memory to all variables and functions which are present in global scope. All variables and functions are stored as key value pair. It stores undefined in case of variables & whole function body in case of function.

    Code Example:

      // Global variable
     var globalVar = "I'm a global variable";
    
     function outerFunction() {
         const outerVar = "I'm an outer variable";
    
         function innerFunction() {
             const innerVar = "I'm an inner variable";
             console.log(innerVar); // Output: I'm an inner variable
             console.log(outerVar); // Output: I'm an outer variable
             console.log(globalVar); // Output: I'm a global variable
         }
    
         innerFunction();
     }
    
     outerFunction();
    

    In this example:

    • In Memory creation phase as globalVar is encountered it'll store undefined as it's value and during code execution phase the actual value will be put in place of undefined.

    • In Memory creation phase outerFunction() , innerFunction() are encountered it'll store whole function body in key value pair.

    • When outerFunction() is invoked, it creates its own execution context.

    • Within outerFunction(), innerFunction() is invoked, creating another execution context.

    • Each function has access to its own variables (innerVar, outerVar) as well as variables in its outer scope (globalVar).

    • After innerFunction() completes execution, its execution context is popped off the call stack, followed by the execution context of outerFunction(). Finally, the global execution context remains.

  2. Code Part: Also known as Code Component, Code Execution Phase & Thread of Execution. In this phase code is executed line by line & as JS encounter a variable during code execution phase it’ll allocate its value in place of undefined.

Types of Execution Context

  • Global Execution Context: It’s the default context. It's created when a program starts running. This represents the environment in which the top-level code executes.

  • Function Execution Context: Created whenever a function is invoked. Each function call generates a new execution context.

Function Invocation

When a function is invoked a new execution context is created & the whole process of memory creation phase and code execution phase will happen for function’s execution context.

Execution Context created for a function will be limited to that function only.

If there is a parameter in a function JS will treat it as variable and allocates memory for it & when we try to access/ console.log any variable inside a Function JS engine will look for that variable in the local memory space(Function’s Execution Context)

Once the function is completed executing and return keyword is encountered function’s execution context will be deleted along with it’s local memory space & it returns the control back to the place where function was invoked.

Execution Context Image

Call Stack

A call stack is used to manage the execution context and maintains the order of execution of execution contexts. It's a stack data structure that follows the Last In, First Out (LIFO) principle. Whenever a function is called, a new execution context is created and pushed onto the call stack. When the function finishes executing, its context is popped off the stack, and the control returns to the place where function was invoked.

  • Whenever a code is executed a global execution context is created and is pushed into the call stack.

  • Whenever a function is invoked a new execution context is created and is pushed inside the call stack.

  • As return keyword encounters the function execution context is poped out of call stack. In the end GEC is also popped out.

Call stack is also known as Execution context stack, Program Stack, Control Stack, Runtime Stack & Machine Stack.

Stack Overflow: It's an error occurs when the call stack exceeds its maximum size due to infinite recursion or deep function nesting.

Call Stack Image

Relationship Between Execution Context and Call Stack

Execution Context Creation: Whenever a function is invoked, a new functional execution context is created and added to the call stack.

  • Execution Context Destruction: After a function completes its execution, its context is popped off the call stack.

  • Nested Function Calls: When functions are nested, each function call generates a new execution context, forming a stack of contexts in the call stack.

Conclusion

Understanding JavaScript's execution context, functional execution context, and call stack is fundamental for mastering the language. By comprehending how these mechanisms work, developers can write more efficient code, diagnose errors effectively, and optimise performance. As you continue your journey in JavaScript development, keep exploring these concepts to deepen your understanding and enhance your skills. Mastering these leads to more efficient, bug-free code, making you a more effective JavaScript developer.