Over a million developers have joined DZone.

JavaScript Execution Context

· Web Dev Zone

JavaScript developers do not pay much attention to the internals of JavaScript execution, namely execution context. Even experienced JavaScript developers lack the necessary knowledge about execution context.  Nevertheless, the concept of execution context is simple. It consists of details for the environment of a function that is executed. To make execution context more clear,  we will try to give some insight for understanding execution context.

First of all, there are two types of execution context: the first one is global and second one is functional. Global context can be accessed from anywhere in the program while functional context  can be accessed by the function itself and inner functions of it. Accessing parent function context results in Scope Chains, which is the ability to access the scope of the calling function. Let’s examine global and functional context with an example:


//global context 
var x = 1; 
function foo(){ 
	//foo context 
	var y = 2; 
	//console.log(x+","+y+","+z); (1) 
	return function inner(){
		//inner context 
		var z = 3; 
		console.log(x+","+y+","+z); //(2) 
	}
} 
//console.log(x+","+y+","+z); (3) 
foo()();

From the above code snippet, the first log will give a reference error because of the variable z, the second log will execute just fine and the third log will give a reference error for y.  The reference errors occur because the current execution context cannot resolve the identifiers. But, each inner function can see its outer function variables. After giving this basic example, let’s dive into details.
JavaScript Execution Context
Browsers interpret JavaScript as single-threaded, which means one thing can be done at one time. Similarly, we can see one execution context at one time. When a page loads, global execution context is created and put into the execution context stack. After that, the interpreter creates a new execution context for each function call while preserving scope chains. Besides, each created execution context is put into the stack with respect to their order. When any of the execution context is finished, the interpreter removes it and continues to execute previous execution context. Below, you can see the figure representing the stack for execution context.
Moreover, execution contexts have a life cycle, that can be divided into creation and execution phase. In creation phase, interpreter follows the steps below:

  1. Each variable, function or argument is created.(Variable Object is created)
  2. Scope Chain is initialized.
  3. Value of “this” is determined.

In execution phase, code is interpreted and executed. Now, let’s observe each steps of creation phase thoroughly.
In creation phase, variable object is created first. Then, arguments object is created. After setting necessary objects, interpreter scans for function declarations and creates a corresponding property for each function in variable object. If there is already reference for the function in variable object, interpreter just overrides it. The same process followed for variable declarations but interpreter just passes declarations that already exists in variable object. After finalizing variable context, scope chain is created and we are ready to run the function. Let’s see below function and how it looks like in creation stage.

function foo(z){
   var x = "Hello World!";
   var y = function(){
      alert(x);
   };
   function f(){};
}
foo(13);

Our function looks like as follows in creation stage.

executionContextForFoo(){
   variableObject : {
      arguments : {
         0 : 13,
         length : 1
      },
      z : 13, // Remember, reference to functions created first.
      f : pointer to the function f 
      x : undefined,
      y : undefined
   },
   scopeChain : {...},
   thisForFoo : {...}
}

At this point, hoisting occurs since we first create pointers to the functions and variables, then execute. Let’s look at the example below.

(function(){ 
	alert(typeof hello);//prints pointer to hello function 
	alert(typeof hi);//prints undefined 
	var hi = function(){ 
		alert("Hi!"); 
	} 
	function hello{ 
		alert("Hello!"); 
	}
})(); 

Function decelerations are always hoisted, any variable is initialized to undefined. In above example, “hi” is a variable and defined as undefined in variable object.
In short, we have tried to explain execution context and give an overview. For more information, you can follow the link below.
Ecma-262

Topics:

Published at DZone with permission of Yusuf Aytaş, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}