Execution Context and Flow of the Program

Consider the following JavaScript code:

var x = 1;
a();
b();
console.log(x);

function a() {
  var x = 10;
  console.log(x);
}

function b() {
  var x = 100;
  console.log(x);
}

When this program runs, the execution flow is managed by the Global Execution Context (GEC) and function-specific execution contexts. Let’s break it down:

1. Global Execution Context (GEC)

When the program starts, the Global Execution Context (GEC) is created. This context has two main phases:

  • Memory Creation Phase: In this phase, memory is allocated for variables and functions but without assigning any values yet.

    • x: undefined (due to variable hoisting)
    • a: function reference (function a is fully hoisted)
    • b: function reference (function b is fully hoisted)
  • Execution Phase: During this phase, code is executed line-by-line, and the values are assigned.

    • x is assigned the value 1.
    • a() is called, and a new execution context is created for function a and pushed to the Call Stack.
    • After a() finishes execution, its context is removed from the Call Stack, and the function-specific execution context is killed.
    • Next, b() is called, and another execution context is created for function b and pushed to the Call Stack.
    • After b() finishes execution, its context is removed from the Call Stack.
    • Finally, the console.log(x) statement executes, printing 1.

2. Function Execution Contexts

When each function is invoked, a new Function Execution Context is created, which has its own memory space and code execution:

  • Execution Context for a():

    • Memory Creation Phase: x is undefined.
    • Execution Phase: x is assigned 10, and console.log(x) prints 10.
    • After this, the execution context is removed from the Call Stack.
  • Execution Context for b():

    • Memory Creation Phase: x is undefined.
    • Execution Phase: x is assigned 100, and console.log(x) prints 100.
    • After this, the execution context is removed from the Call Stack.

3. Call Stack and Execution Flow

  1. Global Execution Context (GEC) is created.
    • x is assigned the value 1.
    • a() is called.
  2. A new Execution Context for a() is created and pushed to the Call Stack.
    • x is assigned 10, and 10 is printed.
    • The execution context for a() is removed from the Call Stack.
  3. Execution Context for b() is created and pushed to the Call Stack.
    • x is assigned 100, and 100 is printed.
    • The execution context for b() is removed from the Call Stack.
  4. The console.log(x) prints 1 from the Global Execution Context.

Output of the Program:

10
100
1

this Keyword and Global Object

When a JavaScript program runs, even if it is an empty file, a global object is created.

  • In Web browsers, this global object is called window.
  • In Node.js, it is called global.

You can access this global object using the this keyword:

console.log(this); // Outputs `window` in browsers or `global` in Node.js

Key Points About this:

  1. Global Scope:

    • In the global context (outside any function), this refers to the global object (window in browsers or global in Node.js).
  2. Inside Functions:

    • In a regular function (not an arrow function), this refers to the object that called the function.
    • In strict mode, this inside a function is undefined unless explicitly bound.
  3. Arrow Functions:

    • Arrow functions do not have their own this context. They inherit this from their enclosing scope.