What is the 'Execution Context' in JavaScript exactly?

My title pretty much sums it all.

Can anyone enlighten me on...

"What is the 'Execution Context' in JavaScript?"

and on how it relates to 'this,' hoisting, prototype chaining, scope and garbage collection?


You're asking about several different concepts that aren't very closely related. I'll try to briefly address each.


Execution context is a concept in the language spec that—in layman's terms—roughly equates to the 'environment' a function executes in; that is, variable scope (and the scope chain, variables in closures from outer scopes), function arguments, and the value of the this object.

The call stack is a collection of execution contexts.

See also this answer and this article.


Scope is literally that: the scope in which a variable can be accessed. Simplistically:

var x;

function a() {
    var y;
}

x can be accessed from anywhere. When a is invoked, x will be in the outer scope. (Stored in the scope chain.)

In contrast, y can only be accessed by code in a() because it is limited to a's scope. This is what the var keyword does: restricts a variable to the local scope. If we omitted var, y would end up in the global scope, generally considered a bad thing.


Think of hoisting as more of a compile-time thing. In JavaScript, function declarations are "hoisted" to the top of their scope. In other words, they are parsed and evaluated before any other code. (This is opposed to function expressions, which are evaluated inline.) Consider the following:

a();
b();

function a() { }
var b = function() { }

The call to a() will succeed because its declaration was hoisted to the top; a was assigned to automatically before program execution began. The call to b() will fail with a TypeError because b will not be defined until line 4.


You have asked so many concepts but lets pick one by one & understand them.

The environment in which your code is running is Execution context. It is created when your code is executed.

Execution Context (Global), created by JS Engine contains 3 important things for you:

  1. Global object - window
  2. Special Object this
  3. Ref to outer environment

Lets see a simple example to understand Global Execution Context:

var a = "Hello World";

function b(){

}

When JS Engine runs this above code it creates following Execution context (shown in image): Global Execution Context


Now let's see how JS Engine creates Execution Context (then we will dig out & understand hoisting): consider this scenario:

b();
console.log(a);

var a = "Hello World!";
function b(){
    console.log("Called b!");
}

I can call the function b() even though it is declared later. This means JS Engine is doing something before my code is executed, lets see what:

JS Engine performs following two steps to while executing any code:

CREATION PHASE :

  • JS Engine parses - run through your code & identifies variables & functions created by code (which will be used in execution phase)
  • Setup memory space for Variables & Functions - "Hoisting"
  • Hoisting - before your code is executed, the JS Engine set asides memory space for Var & Func used inside the code. These variables & functions comprise the Execution Context of any function that is be executed. All variables in JS are initially set to undefined.

Execution PHASE: pretty simple to understand,

  • When the code is executed line-by-line (by JS interpreeter) it can access the variables defined inside Execution Context
  • variable assignment are done in this phase

A new Execution Context is created whenever function invocation is there

Execution Context Stack: What happens when you invoke a function:

function b(){

}

function a(){
    b();
}

a();
  • Now first of all Global Execution Context is going to be created (as explained above)

  • then execution starts and interpreeter encounters call to function a(), and here a new execution context is created pushed on top EC Stack

    so anytime you invoke a function a new EC is created & placed on top of EC Stack.

  • so now EC for a() is CREATED interpreeter will execute the code inside a() line-by-line

  • then intrepreeter encounters call to function b(), this creates another EC which is pushed on top or EC stack

  • When b() finishes it will be popped-off the stack then a() will finish & all the way down to Global EC

see Execution Stack for above code snippet


I have addressed only the topics that are most closely related.

Execution Context is the wrapper around your existing code; which contains code that you have not written; but is generated by the JS Engine.

It comprises of the following -

  1. Global Object
  2. 'this'
  3. Outer environment
  4. Your code

An Execution Context is created each time you run your .js file/app. The first step in this creation phase is Hoisting. The JS Engine reserves space or set's up memory for all the variables and functions defined in your code. These are then accessed when your code is executed line-by-line.

For example:

b();
console.log(a);
var a = "hi!";
function b() {
    console.log("calling function");
}

Here, the function b() and variable a are both accessed before they are defined, however, due to hoisting the console will not throw any error.

The output will look like - (try it)

calling function
undefined

Notice how the function was executed completely, but we have undefined for the variable. This is because Hoisting is performed differently for functions vs variables. The function as a whole is picked up into the memory, but for the variables, space is reserved as a placeholder with the value of undefined. The actual value is then replaced when the engine executes your code line-by-line.

I hope this clears the concept for you.