Understanding function scope and context in JavaScript?


In this tutorial, let us discuss the function scope and context in JavaScript.

Functions are the building blocks of Javascript. Therefore, JavaScript is a functional programming language.

Scope

The 'scope' is the code space where we can define and use a variable in a function. Scopes are of four types.

Global scope

Global 'scope' is the default scope. A variable with global 'scope' is accessible throughout the program. Browser closing removes a global variable. Window objects can access var variables wherein they can't access the let variables.

Functional or local 'scope'

A function variable is accessible only with the function. Variable creation and deletion happen during function start and end. Function parameters work as local variables.

Lexical 'scope'

A nested function is accessible only within the parent function. The child function can access the parent function variables and the global variables, wherein the parent function can not access the child function variables. Lexical 'scope' helps to avoid unnecessary variable reuse.

Block or module' scope'

Let and const keywords by ES6 provides block scope. Variables inside a {} block are accessible only within the code block. Var declaration can't provide block scope. The code block inside an if condition, a for-loop, is an example of block scope.

Users can follow the syntax below to work with the scope.

Syntax

/*Global scope*/
function functionName(){
   /*local scope*/
   if(condition){
      /*module scope*/
   }
   function nested(){
      /*lexical scope*/
   }
}

The syntax above is an abstract of all the scopes.

Example

The program calls the driver function first. Returns a local variable scope. Loop execution is the next where there is a block variable scope using the let keyword. Note that this block variable throws an error when we access it outside the block.

The child function execution is the next. Note that the child function can access the parent variable with lexical scoping. We access the global variable outside the function at last. Accessing the lexical s variable outside throws an error in the catch block.

<html> <body> <h2> Illustrates the function scope </h2> <p id="fnScopClsInp"></p> <div id="fnScopClsBtnWrap"> <button id="fnScopClsBtn"> Get Scope </button> </div> <br> <br> <p id="fnScopClsOut"></p> <script> var fnScopClsBtn = document.getElementById("fnScopClsBtn"); var fnScopClsBtnWrap = document.getElementById("fnScopClsBtnWrap"); var fnScopClsInp = document.getElementById("fnScopClsInp"); var fnScopClsOut = document.getElementById("fnScopClsOut"); var fnScopStr = ""; var globScope = "Global scope"; function functionScope() { var fnScope = "Local or functional scope"; fnScopStr += fnScope + "<br><br>"; function lexicalScope() { var lexScope = "Lexical scope"; for (var i = 0; i < 1; i++) { let blockScop = "Block or module scope"; fnScopStr += blockScop + "<br><br>"; } try { fnScopStr += blockScop + "<br><br>"; } catch (e) { fnScopStr += e + "<br><br>"; } function innerFunction() { var childFn = "Child function"; fnScopStr += childFn + "<br><br>"; fnScopStr += lexScope + "<br><br>"; } innerFunction(); } lexicalScope(); } fnScopClsBtn.onclick = function() { functionScope(); fnScopStr += globScope + "<br><br>"; try { fnScopStr += lexScope + "<br><br>"; } catch (e) { fnScopStr += e + "<br><br>"; } fnScopClsOut.innerHTML = fnScopStr; }; </script> </body> </html>

Context

Context is the environment or the execution space of the code. Context denotes the use of the 'this' keyword. It returns the window object in a global context.

Execution context

Creating a function also creates an execution context. An execution stack controls the context execution order. The scope chain starts from the child function to the parent function and the global scope. There are two execution contexts. Global execution context and local execution context. Execution context has two phases. The creation phase and the execution phase.

Function context

Function context is accessible with the 'this' keyword. Strict mode function reference returns undefined. In normal mode, the function returns the window object. When an object has a method, the 'this' keyword returns the object.

Using call(), apply(), or bind() to invoke the function is another context example. The only difference is the argument change. The function bind() binds the arguments to the new function context.

Users can follow the syntax below to work with the 'context'.

Syntax

function objContext(){
   const objVar ={
      objFn: function(){
         return this;//object context
      }
   };
}
function functionD(){
   "use strict";
   return this;//undefined context
}
function functionC(){
   return this;//window context
}

Some context syntax is in this code snippet.

Example

The execution stack is as follows in this program. Stack pops context B, then context A, and finally context global.

The 'this' keyword inside the function returns the object Window context. An undefined context occurs in the strict mode.

A global context is accessing a global variable. Calling the function with the call() and bind() are other contexts.

<html> <body> <h2> Illustrating the function context </h2> <p id="fnContxtClsInp"></p> <div id="fnContxtClsBtnWrap"> <button id="fnContxtClsBtn">Get context</button> </div> <br> <br> <p id="fnContxtClsOut"></p> <script> var fnContxtClsBtn = document.getElementById("fnContxtClsBtn"); var fnContxtClsBtnWrap = document.getElementById("fnContxtClsBtnWrap"); var fnContxtClsInp = document.getElementById("fnContxtClsInp"); var fnContxtClsOut = document.getElementById("fnContxtClsOut"); var fnContxtStr = ""; var context = "context global"; function objContext() { const objVar = { objFn: function() { return this; }, context: "context object" }; function nestedContext() { return this.context } fnContxtStr += nestedContext() + "<br><br>"; fnContxtStr += "context call " + nestedContext.call(objVar) + "<br><br>"; fnContxtStr += "context bind " + nestedContext.bind(objVar) + "<br><br>"; } function functionD() { "use strict"; return this; } function functionC() { return this; } function functionB() { fnContxtStr += "context B pops first<br><br>"; } function functionA() { functionB(); fnContxtStr += "context A pops second<br><br>"; } fnContxtClsBtn.onclick = function() { functionA(); fnContxtStr += "context global pops finally<br><br>"; fnContxtStr += "context " + functionC() + "<br><br>"; fnContxtStr += "context " + functionD() + "<br><br>"; objContext(); fnContxtClsOut.innerHTML = fnContxtStr; }; </script> </body> </html>

This tutorial taught us scope and context. Scoping your code improves efficiency by reducing bugs and makes debugging easy. It also optimizes naming collisions because we can use the same variable with multiple scopes for different purposes.

Updated on: 15-Nov-2022

158 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements