All you need to know about scopes in JavaScript :-

Chandan KumarChandan Kumar
7 min read

8You write a lot's of js code and some of you may right your first js code.

So i assume that you all know how to create variables, functions and to use them as well.

But did you ever imagine how the JavaScript handle all this variables, functions and also how did it track which variables are accessible in which part of code or how js handle 2 variables with same name and which function can access which variables.

If you ask this question to yourself than this article might be helpful to you. πŸ₯ΈπŸ₯ΈπŸ₯Έ

In this article following topic is help you to understand scope and Closure.

Topic are as follows

  1. Scope

  2. Types of scope

  3. Lexical environment

  4. Lexical scope

  5. Scope chaining

Scope :- πŸ”¬πŸ”¬

Scope is the context or environment in which variables and functions are declared in JavaScript. It also defines which variables and functions are accessible at different parts of the code.

let outer = 11;

function outerCall(){
     console.log(outer);
}
outerCall()
console.log(outer) // 11

So in this scope the variable β€œouterβ€œ is present at the top of the scope so it can accessible throughout the code.

function innerCall(){
     let inner = 11;
     console.log(inner);
}
innerCall()
console.log(inner)  //Uncaught ReferenceError: inner is not defined

Here the variable is declared inside the function so inner variable is only accessible inside innerCall() if we try to access outside the function than it throw an error.

Types of scope :- πŸŒ€πŸŒ€

1. Global scope :- 🌎 🌍

Any variables or functions that are part of the global object (in browsers, it's the window object) have global scope and are accessible from any part of the code.

Or

Variables and functions which have a global scope is accessible to any part of code.

let global_Variables = " hi i have global scope " ;
let global_Count = 0 ;

function call_GlobalScope () {
    console.log (global_Variables);
}
call_GlobalScope(); // hi i have global scope 

for(let i =0; i<3; i++ ){
      global_Count ++ ;
}

console.log(global_Count); // 3

Here ( global_Variables, global_Count ) both have global scope so we can access there variables anywhere inside the function or for loop.

2. Function / local scope :- πŸŽ†πŸŽ†

The variable which created inside the function, loop and block have local scope.

Here the variable or functions only accessible inside the scope where they are declared.

function outer(){

Here the ( inner_Variable, inner function )both present inside the function so they can only accessible within the function only.

If we try to access these outside the function than it throw error.

3.Block scope :- πŸ§ͺπŸ§ͺ

When variables is declared inside the block or conditional statement and loop then the access of that variable is limited to scope inside the block only.

if (true) {
  let add_Value = 20;
  console.log(add_Value);
}
else{
  let remove_Value = 10 ;
  console.log(remove_Value);
}

console.log (add_Value); // ReferenceError: add_Value is not defined

As I told you that the variable declared inside the block is only limited to the block if we try to access the variable outside than it give error .

Lexical Environment :- 🌳🌳

What is a Lexical Environment :- πŸ‘“πŸ‘“

  1. A Lexical Environment is a data structure that holds variable and function declarations along with a reference to its outer (parent) environment.

  2. JavaScript stores variable and know how to access which variables based on where variables, functions, blocks are written in your code.

  3. Lexical refers to the fact that JavaScript determines scope based on how code is written, not when it runs.

  4. Lexical Environment is created when the code is defined, not when it is executed.

Components in Lexical Environment : -πŸ”©πŸ”©

1. Environment Record

The Environment Record is like a storage box that holds all the information about variables, functions, and parameters declared in a particular scope.

It contains Name-value bindings (Name-value bindings, in programming, refer to the association of a name (or identifier) with a value or entity, allowing that value to be referenced or manipulated using the assigned name.) Created by :-

Variable declarations (let, const, var)

Function declarations

Parameters (for function scopes)

let outer_Var = 10;
function environment_Record (name) {
   let greet = "hello";
   console.log(greet + "" + name)
}
environment_Record("Chandan");

Now the main point is that the environment Record is a internal object and conceptually Similar as JavaScript object.

So by Name-value bindings it store value like this :-

1.1 Global Lexical Environment in creation phase :-

Global_Lexical_Environment = {

global_Environment_Record: {
  outer_Var: <uninitialized>//memory allocated but not initialized 
  environment_Record: <function Definition>
},

OuterScope: null,

}

1.2 Global execution phase :-

Global_Lexical_Environment = {

global_Environment_Record: {
 outer_Var : 10
 environment_Record: <function Definition>
},

OuterScope: null,

}

When function call ( environment_Record(name) )

Than

1.3 Function Lexical Environment creation phase :-

Function_Lexical_Environment = {

 environment_Record:{
      name : "Chandan",
      greet: Memory allocated but not initialized 
   },
OuterScope: global Lexical Environment 

}

1.4 Function Execution Phase :-

Function_Lexical_Environment = {

environment_Record = {
      name: "Chandan",
      greet: "hello"
 },
OuterScope: global Lexical Environment 
}

2. Outer Lexical Environment Reference

This is a reference (or a pointer) to the parent Lexical Environment β€” the environment in which the current function or block was defined, not where it was called.

This reference allows JavaScript to build the scope chain, so it can look up variables not found in the current environment.

let outer_Var = 10;

function environment_Record (name){
    let greet = " hello " 
    Console.log(greet  + "" + name ); 
    Console.log(outer_Var) // we get the values from global Lexical Environment 
}
environment_Record("Chandan");

Lexical scope :-

  1. Lexical Scope is the ability of a function to access variables from its parent scope, based on where the function is physically written in the code.

  2. In JavaScript, functions are lexically bound to the scope in which they are defined not where they are called.

  3. This means a function defined inside another function will always remember the environment in which it was created.

function parents(){
    let car = "Audi";
      function child () {
           console.log("child have car," , car);
      }
        child();
}
parent();
// console.log (car) // error car not defined

Explanation:

According to the definition, the child() function is lexically bound to its parent function parent(). That means it has access to all variables defined in the parent() function's scope, such as car.

However, trying to access car outside of the parent() function results in an error, because car is not defined in the global scope.

Scope Chaining :-

Suppose you live in a building and you are on the 1st floor You’re trying to find your wallet, so you first check your own floor. If you don’t find it there, you go to the 2nd floor. Still not there? You go to the 3rd, then 4th, and so on, until you either find the wallet or reach the top floor and confirm it's nowhere to be found.

In the same way, JavaScript performs scope chaining.

When an inner function tries to access a variable:

  1. JavaScript first looks for the variable in its current scope.

  2. If it’s not found, it moves up to the parent scope.

  3. If still not found, it keeps moving up the chain of lexical scopes.

  4. Until it either finds the variable or reaches the global scope.

  5. If it doesn’t find the variable even in the global scope, it throws a `ReferenceError`.

Example of scope chaining:-

let wallet = "In global scope";

function first_Floor() {
   console.log("Not found go to secondFloor");

    function second_Floor() {
         console.log("Not found go to thirdFloor");
         function  third_Floor () {
              console.log("Not found go to  fourth Floor");
              function fourth_Floor() {
                  console.log("founded", wallet);
              }
              fourth_Floor();
         }
         third_Floor();
    }
    second_Floor(); 

}
first_Floor();

The variable wallet is declared in the global scope.

Inside fourth_Floor(), JavaScript tries to find wallet:

1. It looks in fourth_Floor() β†’ not found.

2. Then in third_Floor() β†’ not found.

3. Then in second_Floor() β†’ not found.

4. Then in first_Floor() β†’ not found.

5. Then in the global scope β†’ βœ… found!

Resources

Article

https://dev.to/codecraftjs/variable-scope-and-scope-chain-in-javascript-35oi

https://medium.com/@mohdtalib.dev/lexical-environment-in-javascript-a2112b78a3cb

https://blog.webdevsimplified.com/2022-10/js-scoping/

Videos

https://youtu.be/cHHU0jXfjKY?si=9BYI8T1nhaC91HlP

https://youtu.be/uH-tVP8MUs8?si=PFaw8nqHEBJq0Wc4

https://youtu.be/14H2TsrjcLo?si=tCnMbTYuTcNa3exI

Hope you find this article helpfull and learn something from it .πŸ˜‡πŸ˜‡

So please share your feedback with me it means a lot thanks 😊

0
Subscribe to my newsletter

Read articles from Chandan Kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chandan Kumar
Chandan Kumar

Tech enthusiast CSE student | Python, JS, Node.js, Web Dev | Learning DSA and exploring Web 3.0 πŸš€