JS — Scopes,Types,chaining and lexical scope and Environment

Rajesh Kumar
7 min readJun 25, 2020

In this article ,we will discuss about what is JS scope,it’s different types and how Js differentiate different type of scoping to process the variable and which environment helps it to understand the scoping in much easiest way!! Every beginner should have clear understanding about these things.

So let’s begin our discussion with scoping in JS!!

What is scope in JS?

In JS scope refers to — the accessibility (visibility) of the variables.

So basically it’s define where you can use/access a variable or not.

Importance of Scope!!

  • The most important benefit of scope is security. That means you can’t access variable that is not available for the area of program or that is not exist for that particular area of program.
  • This also helps in to avoid name collisions.It’s allow to use same variable name in different scope

There are different types of Scope in JS.

Types of Scope

There are three types of scope in JS:

  1. Global scope
  2. Function Scope or Local Scope
  3. Block scope

Let’s discuss each scope one by one.

  1. Global Scope

Any variable that’s not declared inside any function or block (a pair of curly braces) of a program, is inside the global scope. The variables that are in the global scope can be accessed from anywhere in the program. For example:

var msg= 'Welcome XYZ!!';function getMessage() {
console.log(msg);
}
getMessage(); //'Welcome XYZ!!'

2. Function Scope or Local Scope

Any variable that’s declared inside a function ,is inside the local scope. They can only be accessed from within that function in which that are declared and that means they can’t be accessed from the outside code or outside the function. For example:

function getMessage() {
var msg= 'Welcome XYZ!!';
console.log(msg);
}
getMessage(); //'Welcome XYZ!!'
console.log(msg); // Uncaught ReferenceError: msg is not defined

3. Block Scope

Any variable that’s declared inside a curly braces i.e{},is inside the block scope. They can only be accessed from within that function in which that are declared and that means they can’t be accessed outside the curly braces i.e{}.

ES6 introduced — let and const variables, unlike var variables, they can be scoped to the nearest pair of curly braces. For example:

{
let fName= "XYZ";
const age = 20;
var city= "ABC";
console.log(fName); // "XYZ"
console.log(age); // 20
console.log(city); // "ABC"
}
console.log(fName); // Uncaught ReferenceError: fname is not defined
console.log(age); // Uncaught ReferenceError: age is not defined
console.log(city); // "ABC"

Note: var variables can be used outside the block, that is, var variables are not block scoped.

We have seen different types of scope in JS. Now we can also nested the scope as function .let’s see with an example.

var fName= "XYZ";
function getMessage() {
let msg= 'Welcome';
{
const city= "ABC"
console.log(`${msg} ${fName} in ${city}`);
}

}
getMessage(); // Welcome XYZ in ABC

In the above example,we have 3 different scopes that are nested within each other.First one is block scope that is created due to const city and nested inside function block.Second one is function/Local scope that nested inside third one i.e Global scope.

Now the questions here arise that how JS understand that variable is inside which scope? How it’s differentiate it and process variables based on scope? 😵

Actually JS acheive it by — lexical scope and lexical environment . I’m pretty sure after understanding these two ,you will definitely have the clear and in-depth knowledge about the scope,how JS process variable and distinguish different scope.✔

What is Lexical Scope?

The scope which is identified at the lexing time (generally referred to as compiling) rather than at runtime.

It’s also known as static scope.

let’s take an example

let marks = 70;

function displayMarks(){
console.log(marks);
}
function changeMarks(){
let marks = 50;
displayMarks();
}
changeMarks(); // 70

In the above,many of you are expecting o/p: 50 but actual o/p is 70. It will always give o/p 70 no matter wherever you call displayMarks().

Your expecting output i.e 50 was right if JS supports dynamic scope. In Dynamic scope — outputs depends on from where the function displayMarks() is called then o/p will be varied.

Because by using lexical scope we can only determine the scope of the variable just by looking at the source code. Whereas in the case of dynamic scoping the scope can’t be determined until the code is executed.

Most of the programming languages support lexical or static scope such as C,Java, JavaScript. Perl supports both static and dynamic scoping.

JS supports lexical scope where scope is determined at compile time .This process is known as scope chaining.

Let’s understand the chaining with an example:-

let msg = "Welcome";
function display() {
let fName= "XYZ";
console.log(fName); // XYZ
console.log(msg); // Welcome
city = "ABC";
console.log(city); // ABC
}
display();

In this when we invoked display,JS enginee first looks for the fName .It’will search in first at current scope and find it in function/local scope.Next It will looking for msg first it will search in current scope it’s not available there then it will look in outer scope and it finds msg there which is global scope. Next, Js enginee search for city,first it will look in current scope it’s not there so then it will look in outer scope it’s not also in outer scope.It will again look into another outer scope but there is no other scope available.

So does mean it’ll throw error? Yes you are right if we strict mode was available/enable i.e ‘use strict’ .Yo can learn about it in detail in my another Strict mode article. 😉

But since here strict mode is not enable so engine will create a new variable named city and assign ‘ABC’ to it.

So by scope chain the engine the will traverse until it finds the variable ,when a variable is used .

But the main question here is that how JS engine works i.e looking for variable in different scope? And the answer using lexical environment.

let’s understand the last topic and after that you actually understand the whole concept of scope and chaining.

Lexical Environment in JS!!🤦‍♂️

lexical environment — refers to a structure that contains the identifier-variable mapping.

  • **Identifier:- refers to the name of variables/functions .
  • **Variable:- refers to the actual object that’s including function object and array object or primitive value (i.e used to referred to the value)

So in simple words we can say that lexical environment is a place where variables and reference to the object are stored.

Note: lexical environment is created for each lexical scope when lexical scope invoked/executed.

At concept level lexical environment looks like below:

lexicalEnvironment = {
fname: 'XYZ',
obj: <ref. to the object>
}

Each lexical environment also has a reference to its outer lexical environment ( i.e outer scope) if that is exist or null if not exist an outer lexical.

lexicalEnvironment = {
fname: 'XYZ',
obj: <ref. to the object>,
outer: <outer lexical environment>
}

Now let’s see how JS engine using lexical environment for looking up of the variables.

I’ve taken a simple example that will help you to understand it without any difficulties.

let fName= "XYZ";function getMessage() {
let msg= "Welcome";
console.log(`${msg} ${fName});
}
getMessage(); // Welcome XYZ{
let fName= "ABC"
console.log(fName); //ABC
}

when above program will execute ,a outermost lexical environment(i.e global environment) will be created.It’s contains the all function (i.e getMessage) and variable (i.e fName) define inside it and contains the reference of outer lexical environment null because there is not any outer scope available .

globalLexicalEnvironment = {
fName: 'Welcome'
getMessage: <ref. to greet function> ,
outer: <null>
}

After that a function i.e getMessage is invoked .So a new lexical environment is created (because we have discussed that for every lexical scope execution there will be a new lexical environment).Which contains all the variable i.e(msg) and the function reference(i.e here no such function availble for this scope) that is declare inside or call inside it’s current state .It’s outer scope reference will be globalLexicalEnvironment(because it is outer scope for this function).

functionLexicalEnvironment = {
name: 'Peter',
outer: <globalLexicalEnvironment>
}

So here when console.log(`${msg} ${fName}); it’s search for msg & fname variable ,msg variable is available in current lexical environment but fname is not so it will look for outer scope environment(i.e in this case globalLexicalEnvironment is outer scope). it will search in this scope and it will available.

Next JS engine executes the code inside the code block.So it will create a new lexical environment for the block.which store the the current scope variable i.e fName and function ref (i.e not available for this scope) and outer scope i.e in this outer lexical environment is globalLexicalEnvironmen t.Next it will execute console.log(fName); and looking for fName in it’s local scope.and it find in current state so it will not looking in other outer scope.

blockLexicalEnvironment = {
fName: 'ABC',
outer: <globalLexicalEnvironment>
}

Note — A new lexical environment is created only for let and const declarations, not var declarations. var declarations are added to the current lexical environment (global or function lexical environment).

i.e Here functionLexicalEnvironment and blockLexicalEnvironment created due to let fName and let msg after the execution of function and block.

That’s how all scope ,chaining ,environment of JS concepts works for a variable!!. 😃

I hope all of your concept has been cleared!!! If you really liked this article click the clap 👏button below. Also write your feedback and queries in comment section.

--

--