Scope Chain & Lexical Environment in Javascript
Tags: javascript, programming, codenewbie, scope
Published: 2021-01-08 20:28:29

Scopes and Lexical Environment are a fundamental concept of JavaScript that every JavaScript developer should know and understand. Yet, it’s a concept that confuses many new JavaScript developers.

So in this article, I will try to explain all these concepts and how they really work in JavaScript.

## Scope

> Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript.

There are two types of scope in JS:

- Global Scope

- Local Scope

**Points to remember:**

- Variables defined inside a function are in the local scope
- Variables defined outside of a function are in the global scope. 
- Each function when invoked creates a new scope.

## Global Scope

When you start writing JavaScript in a document, you are already in the Global scope. There is only one Global scope throughout a JavaScript document. A variable is in the Global scope if it's defined outside of a function.


```javascript
var language = 'JS';


``` 

Variables inside the Global scope can be accessed and altered in any other scope.


```javascript
var language = 'JS';

function handleChange(){
    console.log("Inside Function before modification-> ", language);
    language = 'PHP';
    console.log("Inside Function after modification-> ", language);
}

handleChange();

console.log("Outside function-> ", language);
``` 


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1610128940567/i3yv8oXtH.png)

## Local Scope

Variables defined inside a function are in the local scope. And they have a different scope for every call of that function. This means that variables having the same name can be used in different functions. This is because those variables are bound to their respective functions, each having different scopes, and are not accessible in other functions.



```javascript
var language = 'JS';

function a() {
    var language = 'PHP'
    console.log("Inside Function a()-> ", language); //Output: PHP
    function b() {
        var language = 'C++'
        console.log("Inside Function b()-> ", language); // Output: C++
    }
    b();
}

a();

console.log("Outside function-> ", language); //Output: JS
``` 


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1610129368487/Z1hcx7E2J.png)

This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack. A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.



## Block Statements

Block statements like `if` and `switch` conditions or `for` and `while` loops, unlike functions, don't create a new scope. Variables defined inside of a block statement will remain in the scope they were already in.


```javascript
if(true){
    var language = 'JS';
}

console.log(language); // Output: JS
``` 

Contrary to the `var` keyword, the `let` and `const` keywords support the declaration of **local scope** inside block statements.


```javascript
if (true) {
    var language = 'JS';
    const language2 = 'PHP';
    let language3 = 'C++';

    console.log("===Inside Block Statement===")
    console.log(language); // Output: JS
    console.log(language2); // Output: PHP
    console.log(language3); // Output: C++
}

console.log("===Outside Block Statement===")

console.log(language); // Output: JS
console.log(language2); // Output: ReferenceError
console.log(language3); // Output: ReferenceError
``` 


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1610130026995/SWY_wQ1YR.png)


> Global scope lives as long as your application lives. Local Scope lives as long as your functions are called and executed.


## Scope Chain

> The Scope Chain is the hierarchy of scopes that will be searched in order to find a function or variable.
 
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1610133490141/DgG9zwudY.png)

In the creation phase of the  [execution context](https://dev.to/anuradha9712/execution-context-in-javascript-43l7), the scope chain is created after the variable object. The scope chain itself contains the variable object. 

The Scope Chain is used to resolve variables. When asked to resolve a variable, JavaScript always starts at the innermost level of the code nest and keeps jumping back to the parent scope until it finds the variable or any other resource it is looking for. The scope chain can simply be defined as an object containing the variable object of its own execution context and all the other execution contexts of its parents, an object having a bunch of other objects.


## Lexical Scope

Lexical Scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. This means that the child's functions are lexically bound to the execution context of their parents. Lexical scope is sometimes also referred to as **Static Scope**.

```javascript
function a() {
    var language = 'PHP'
    console.log("Inside Function a()-> ", language); //Output: PHP

    function b() {

        console.log("Inside Function b() before modification-> ", language); // Output: PHP
        language = 'C++'
        console.log("Inside Function b() after modification-> ", language); // Output: C++

        var count = 3;
        console.log("Count inside b()-> ", count); //Output: 3
    }

    b();
    console.log("Inside Function a() after modification-> ", language); // Output: C++
    console.log("Count inside a()-> ", count); //Output: ReferenceError
}

a();

``` 


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1610134808136/vEGOvVGI_.png)


> Lexical Scope works in a forward manner.

`language` can be accessed by its children's execution contexts. But it doesn't work backward to its parents, meaning that the variable `count` cannot be accessed by its parents.


## Lexical Environment

Every time the JavaScript engine creates an execution context to execute the function or global code, it also creates a new lexical environment to store the variable defined in that function during the execution of that function.

A **lexical Environment** is a data structure that holds an *identifier-variable* mapping. (here identifier refers to the name of variables/functions, and the variable is the reference to actual object [including function type object] or primitive value).

A Lexical Environment has two components: 

- **Environment record:** is the actual place where the variable and function declarations are stored.
- **Reference to the outer environment:** means it has access to its outer (parent) lexical environment. 

A lexical environment conceptually looks like this:


```javascript
lexicalEnvironment = {
  environmentRecord: {
    <identifier> : <value>,
    <identifier> : <value>
  }
  outer: < Reference to the parent lexical environment>
}
```

let's try to understand this using a simple example:


```javascript
let language = 'JS';
function a() {
  let b = 25;  
  console.log('Inside function a()');
}
a();
console.log('Inside global execution context');
``` 

When the JavaScript engine creates a global execution context to execute global code, it also creates a new lexical environment to store the variables and functions defined in the global scope. So the lexical environment for the global scope will look like this:


```javascript
globalLexicalEnvironment = {
  environmentRecord: {
      language    : 'JS',
      a : < reference to function object >
  }
  outer: null
}
``` 

Here the outer lexical environment is set to `null` because **there is no outer lexical environment for the global scope.**

When the engine creates an execution context for a() function, it also creates a lexical environment to store variables defined in that function during the execution of the function. So the lexical environment of the function will look like this:


```javascript
functionLexicalEnvironment = {
  environmentRecord: {
      b    : 25,
  }
  outer: <globalLexicalEnvironment>
}
``` 

The outer lexical environment of the function is set to the global lexical environment because the function is surrounded by the global scope in the source code.


When a function completes, its execution context is removed from the stack, but its lexical environment may or may not be removed from the memory depending on if that lexical environment is referenced by any other lexical environments in their outer lexical environment property.

## Wrap Up!!

Thanks for reading!! I know this is a lot to consume in a single article. I hope it was helpful to some extent. Please share it with your network. Don’t forget to leave your comments below.

[![Buy-me-a-coffee](https://cdn.buymeacoffee.com/buttons/v2/default-blue.png)](https://www.buymeacoffee.com/anuradha2612)