Buildtide
Author: Hussain Mir Ali

I am interested in web and mobile technologies.

If you have any questions or feedback then message me at devtips@Buildtide.com.

Scope in JavaScript

Scope in JavaScript is a crucial mechanism that helps manage visibility of functions, objects and variables. In this blog post different aspects of scope have been discussed and how they can be leveraged for writing efficient JavaScript code.

Execution Context

Execution context is the environment/scope wherein a piece of code is executed. Execution context has 3 main components that help JavaScript manage program execution. The 'Variable Object' contains information about variables associated with current execution context, the 'Scope Chain' is useful to find variables missing from current execution context and 'this' is the owning object of the code. Execution context and context('this') are different concepts. To learn more about 'this' please read this post: Context in JavaScript .

Variable Object

In JavaScript variable object contains information about variables related to the current execution context.

The global object contains information about variables in the global execution context(window) like globally available variables and function declarations.

The activation object is a special case of variable object for functions. So it contains the formal arguments of the function itself, default 'arguments' object, local variables and local function declarations.

Execution Context Stack

Initially when the browser loads JavaScript code it is in global execution context. But JavaScript functions have their own execution context and it can get complicated with nested functions. So the execution stack is used to keep track of the current execution context during program execution. It is a stack data structure and when a function is executed a new context is pushed onto the stack then it is popped once function execution is complete. The global execution context is always at the bottom of the stack.

function function4(){
  function3();
  function function3(){
    function2();
    function function2(){
      function1();
      function function1(){
        console.log('reached end.');
      }
    }
  }
}

function4();

The above image visualizes execution stack pertaining to the sample code. When 'function4' is invoked then all the nested functions will be invoked sequentially. The interpreter will push each execution context on to the stack. So when 'function4' is invoked the execution stack will have 'function1' since it is the last one to be invoked. This means that the inner most function will complete executing first so when 'function1' is executed its execution context is popped of the stack. Then the top of the stack will have execution context for 'function2' and when it complete execution then its execution context will be popped of the stack as well and 'function3' will be at the top. This goes on until 'function4' complete execution and it is also popped of the stack. 'Global Execution Context' always remains on the execution stack.

Scope Chain

Each execution context has a scope chain associated with it. So all functions in the code that have execution contexts will also have respective scope chains. Each scope chain is a collection containing the variable object of current execution context and variable objects of all the parents. So if a variable is not found in current execution context during execution then JavaScript engine will traverse up through the scope chain until it reaches the global execution context and return error if nothing was found.

function function4(){
  function3();
  function function3(){
    function2();
    function function2(){
      function1();
      function function1(){
        console.log('reached end.');
      }
    }
  }
}

function4();

The above execution stack represents the scope chain for each execution context for all functions in the sample code. Scope chain for 'Global Object' only has one member which is itself. When 'function4' is invoked then the interpreter will create a scope chain having itself as the member and the root as 'Global Object'. Similarly when 'function3' is invoked then interpreter will create its scope chain having 'function3' at the bottom superseded by 'function4' and the root being 'Global Object' context. This will go on until 'function1' is invoked so its scope chain will have all execution contexts going back to 'Global Object'.