What the GEC and FEC ?!

What the GEC and FEC ?!

In the previous article, we learned about how the Macro and Micro tasks are scheduled in task queues for the non-blocking behaviour and how event loop prioritises Micro tasks over Macro tasks. We also learned that call stack is where all code/tasks are executed by storing the function calls in LIFO order. Today, we will go little deeper to understand how the function calls are executed within the call stack.

Execution Context

Execution context is an environment created by the JavaScript engine to execute the JS code. This context includes all the necessary information for the program to execute. It can be thought as a staging area where all the required objects are made available to perform the execution such as variables and functions. GCE and FEC are the two types of those contexts.

GEC: Global Execution Context

GEC is the first thing that is created in the script execution. It is the default or base execution context. All the variables and functions that are not inside any function are attached to the global object. In Node it is called global object and in browsers it is the Window object.

Before the code execution starts, variables that are declared with var are attached at the top of the global object initialised with 'undefined' value. Function declarations are attached along with the function definition. This means, var variables and functions can be accessed from anywhere in the code, even before their declaration. But the value of the variables remain undefined until their assignment. This is called Hoisting.

Hoisting

In the above code, the var1 is accessed and test function is called before their declaration. This doesn't give error like in the other programming languages. Because, they are hoisted in the execution context with undefined and function definition respectively. The output will look like this.

undefined
inside test
10        

Technically, the execution context creates a Lexical environment to store the variables and functions. Block scoped variables (let and const) are added in a 'block lexical environment'. However, they are not hoisted like var. They are kept in a Temporal Dead Zone(TDZ) during the creation of the execution context, making them inaccessible before their declaration.

The code that is present in the global context is started to execute first. So, the GEC is the first one to be added in the call stack. When a function is invoked, a new execution context is created which is called the functional execution context.

FEC: Functional Execution Context

FEC is created when a function is invoked. This is just like the GEC but with the function's arguments, variables and functions inside that. Variables with var declarations and functions that are part of the current function are hoisted to the top of the functional context.

Here comes the fascinating part. The variables and functions belonging to the global context (i.e., global lexical environment) are also available to the functional context. Similarly, if the current function has another function inside it, the inner function has access to the lexical environment of the outer function as well as the global context. This is because the current context's lexical environment has a reference to its parent's lexical environment. This is called Scope Chain.

If a variable is not found in the current context, it will look up in the scope chain till it reaches the global context. If the variable is not found until the global context, it will throw a reference error. Also, the variables and arguments are available to consume inside the inner functions (like callback functions). Even after the outer function has completed executing, the outer lexical environment will still be present as long as the variables are referred in the inner/callback functions. This behaviour is called Closure.

Closure

If we inspect this code, var1 is in the global context, var2 and arg1 are in test functional context. They are still available to access in innerTest. So, the above code will produce the following output. But the reverse is not true. The inner function context can't be accessed from parent function context.

inside innerTest 10 20 5        

Execution Stack

As the call stack stores and executes the execution contexts, it is also known as the execution stack. All execution contexts go through creation, execution and deletion phases.

  • During the creation phase, Global or Functional lexical environment is created. var variables and functions are hoisted. Scope chain is formed in the order of how functions are written. let and const are put in the TDZ. And, the context is put on the execution stack.
  • In the execution phase, the code is evaluated and variables are assigned to the given values. The context which is on the top of the stack becomes active execution context and the code inside it is executed line after line. If any function call is encountered, new FEC is created on top of that and becomes the active execution context.
  • Once all the code inside an FEC is finished (either finished or callback scheduled in task queue), it is popped out of the stack and the control goes to the previous execution context.

When the GEC becomes the active execution context (i.e., no FEC is present in the call stack), the call stack is considered as empty. GEC stays in the call stack through out the JS program execution. It is popped out only when all the code and callback tasks are executed or when the JS engine is terminated.

So, the execution context is responsible for the seamless execution of JavaScript code. By leveraging lexical environments and scope chaining, we enable powerful features like closures and hoisting. Additionally, the task queue and event loop make JavaScript exceptionally efficient at handling complex tasks with ease and minimal resource consumption. Explore more examples to deepen your understanding of closures, especially in callback functions. Happy scripting !!

要查看或添加评论,请登录

Shenbaga Praburaj A的更多文章

  • Endless love between Call stack and Task queue

    Endless love between Call stack and Task queue

    Well, we all know, Javascript is a single threaded language and it can only execute one thing at a time. But, how do we…

    1 条评论
  • Does await really await?

    Does await really await?

    The 'await' keyword in javascript is used to wait for a Promise. It can only be used inside an 'async' function.

    1 条评论

社区洞察

其他会员也浏览了