Execution in JavaScript

Execution in JavaScript

Ever wondered how your JavaScript codes are being executed? Why variables declared in a function are only accessible when the function is called? And what really goes on behind the scenes? Then this article should help clear most of your curiosity. In this article, I'll explain how JavaScript executes programs(Execution context) and the order in which programs are executed(Execution stack).

Prerequisites

  • Fundamental knowledge of JavaScript ( Variable and Function declaration. )

  • Code Editor and Browser

Since this article is not intended to fully explain the workings of fundamental JavaScript such as variable and function declaration, I recommend this JS fundamentals article for better clarity.

Now that we're familiar with the fundamentals of JavaScript, let's dive in.

What is an execution context?

The JavaScript execution context is the environment in which JavaScript code is executed. When JavaScript code is executed, the engine creates an execution context to manage the code's execution process. The execution context tells which part of the code can use the code's functions, variables, and objects.

Type of execution context

There are three types of execution contexts.

  1. Global execution context (GEC)

  2. Function execution context (FEC)

  3. Eval execution context

Global Execution Context(GEC)

When you write JavaScript code, it is executed in an environment called the global execution context. This is like a stage where your code is run. The global execution context is created at the start of the execution and is always the first execution context to be created. It is responsible for executing your global code and creating the global object (i.e, a big container that holds all the information about your code.)

Functional execution context(FEC)

The functional execution context is the context produced by the JS engine whenever a function call is encountered. Each function has its own context of operation. The functional execution context has access to all of the code in the global execution context but not vice versa. This is a term referred to as "lexical scoping." When a JavaScript engine executes code for the global execution context, it creates a new execution context for any function calls it encounters, called the function execution context(FEC).

Eval Function

In JavaScript, the eval function is used to execute a string of JavaScript code at runtime. When eval is called, it takes a string of JavaScript code as an argument and evaluates it in the current execution context. This means that any variables or functions defined in the current context will be accessible to the code being evaluated by eval.

The eval function can be useful in certain situations, such as when you need to dynamically generate and execute code based on user input or external data. However, it can also be a source of security vulnerabilities if used improperly, so it is generally considered best practice to avoid using eval whenever possible.

Creation of the execution context

  1. Creation phase

  2. Execution phase

Creation phase

In JavaScript, the creation phase of the execution context refers to the initial setup that occurs when a new execution context is created. This phase happens before code is executed in the context.

During the creation phase, the JavaScript engine performs several important tasks, including:

  • Creating a new variable environment, which includes the creation of a new this binding and the creation of new arguments object.

  • Creating a new lexical environment, which defines the scope in which variables and functions are defined and can be accessed.

  • Initializing the arguments object and any local variables declared in the context with the values passed to the context.

  • Setting up any try/catch statements or other control flow structures that are present in the code.

The creation phase is an important part of the overall execution of JavaScript code, as it sets the stage for the code that will be executed in the context. It is during this phase that the JavaScript engine prepares the environment in which the code will run, and determines what variables and functions will be available to the code.

Execution Phase

In JavaScript, the execution phase of the execution context refers to the phase in which code is actually executed in the context. This phase follows the creation phase, and occurs after the JavaScript engine has prepared the environment and set up the this binding, variable environment, and other necessary components.

During the execution phase, the JavaScript engine will execute the code in the context one statement at a time, starting at the beginning of the code and working its way through to the end. As it executes each statement, the engine will update the variable environment and other components of the context to reflect the changes made by the code.

The execution phase is the final step in the JavaScript execution process, and it is where the code in the context is actually executed and the desired results are produced. Once the execution phase is complete, the execution context is terminated and any memory it was using is freed up for other purposes.

Execution stack(call stack)

In JavaScript, the execution stack (also known as the call stack) is a data structure that is used to store the currently executing functions. It is essentially a list of all the functions that are called in a program, with the most recently called function at the top of the stack. This data structure follows the last in, first out (LIFO) structure, and Javascript is single-threaded, which means it only performs one task at a time. The global execution context is at the very bottom of the stack, and it is the default of the call stack when execution starts. In the global execution context, when a function is created, it immediately creates a function execution context and moves it to the top of the call stack. It then stops running code in the global execution context and runs the code at the top of the call stack, which in this case is the newly created function from the global execution context. When the function's execution is complete, it is popped from the call stack, and the code in the global execution context resumes execution. If, while executing the function that was seen in the global execution context, an embedded function is seen, the execution of code in the first function is paused, and the new embedded function moves to the top of the call stack and is therefore executed first before returning to the first function and then to the execution context.

var a = 10;
function functionA() {
    console.log("Start function A");
    function functionB(){
        console.log("In function B");
    }
    functionB();
}
functionA();

function functionC() {
    console.log("In function C");
}
functionC();
console.log("GlobalContext");

To understand the execution stack, let's consider this code above

When the script loads in the JavaScript engine, by default, the global execution context is placed at the very bottom of the stack, and it starts execution. The var a = 10 is encountered in the GEC and stored in the variable object. Upon seeing the functionA() call, the JS engine creates a new FEC, adds it to the top of the execution stack, and starts executing. As you can see, functionB() was invoked inside the first function; therefore, the JS engine creates a new FEC and inserts it at the top of the stack for functionB(). When functionB() is done executing, it is removed from the call stack and returns back to functionA(), and in the absence of any more code to execute, functionA()'s execution is complete, and it is all also kicked off the call stack and now back to the global execution context. When the whole code has been completed, the JS engine removes the GEC from the current stack, and JavaScript execution concludes.

Conclusion

In conclusion, the execution context is a fundamental concept in JavaScript that is essential for understanding how the interpreter manages the execution flow of a program. By understanding the execution context, you can write better and more efficient code, debug your code more effectively, and write more modular and reusable functions. For more information on the execution context, be sure to check out the documentation on the JavaScript official website, or explore some of the online tutorials and resources available.