Understanding Variable Scope in JavaScript
Tags: javascript, webdev, programming, beginners
Published: 2022-08-09 10:29:47

When programming, understanding the concept of scope is essential as it can help you understand, design, and debug your code better.

In a JavaScript program, a scope is the section of the program where a variable can be accessed. Beyond the environment defined by this scope, it is effectively invisible and therefore, cannot be used or called. This makes it possible for instance, to use the same name for variables declared within different scopes.

Consider this code snippet:

```javascript
const color = "green";

if (true) {
  const color = "red";
  console.log(color); // OUTPUT: red
}

function printColor() {
  const color = "blue";
  console.log(color); // OUTPUT: blue
}
printColor();

console.log(color); // OUTPUT: green
```

It might initially seem confusing that the code snippet above runs fine, despite the fact that the `color` variable seems to have been redeclared and assigned a value three times, using the `const` keyword (which should be impossible).  However, the concept of __Scope__ makes this possible. 

Let's now see the types of scope there are.

## TYPES OF SCOPE

Types of scope in JavaScript include:

- Global scope
- Block scope
- Function scope
- Lexical scope

### GLOBAL SCOPE

A variable has global scope if it is declared at the top of a program before everything else and outside of any code block or function within that program. This scope is the root level where a program starts to execute by default, and so variables declared here can be accessed at any point throughout the program by functions or statements.

Example:

```javascript
let color = "green"; // This 'color' variable has Global scope

if (true) {
  console.log(color); // OUTPUT: green
}

function printColor() {
  console.log(color);
}
printColor(); // OUTPUT: green
```

The `color` variable is globally scoped and therefore can be accessed within the `if` statement block and the `printColor()` function body by the `console.log()` method.

### BLOCK SCOPE

If you declare a variable with the keyword `const` or `let` within any code block bounded by braces `{}`, that variable is block-scoped to this code block. It is local to this block and therefore, only accessible within the environment defined within its opening and closing braces `{}` and is inaccessible to functions and statements outside it.

Examples of block-scoped variables include those declared within `if` and `while` loop statement blocks with either the `let` or `const` keyword.

Variables declared with the `var` keyword are an exception as they have either global scope or are scoped to the closest function within which they are nested.

Example:

```javascript
if (true) {
  let color = "green"; // This 'color' variable has Block scope
}

{
  let color = "green"; // This 'color' variable has Block scope
}

console.log(color); // OUTPUT: Uncaught ReferenceError: color is not defined
```

The code snippet above outputs an error message because the `console.log()` method accepts a parameter, the `color` variable, which it does not have access to because it was called outside the variable's block scope.

```javascript
if (true) {
  let color = "green";
  console.log(color); // OUTPUT: green
}
```

The code snippet above now runs fine without displaying an error message because the `console.log()` method is now called within the block scope of the variable `color`, and therefore has access to it.

### FUNCTION SCOPE

A variable declared with the `const`, `let` or `var` keyword within a given function's body, is local and scoped to this function. It is only accessible within this function's body and inaccessible outside it. An exception to this is a type of function called a [closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) (a combination of a function and its lexical environment).

Example:

```javascript
function printColor() {
  let color = "green"; //This 'color' variable has Function scope
}
printColor();
console.log(color); // OUTPUT: Uncaught ReferenceError: color is not defined
```

Running the code snippet above outputs an error message because the `color` variable is scoped to the `printColor` function, so the `console.log()` method called outside of this variable's scope does not have access to it.

```javascript
function printColor() {
  let color = "green"; //This 'color' variable has Function scope
  console.log(color);
}
printColor(); // OUTPUT: green
```

In the code snippet above, the `console.log()` method is called within the function scope of the `color` variable, so it now has access to this variable and the code runs fine.

### LEXICAL SCOPE

Within a program, there can be nested combinations of functions, statements and other code blocks. Their scopes are similarly nested within each other such that each scope has access to the outer scope or parent scope it was defined in.

Therefore a variable's lexical scope is an aggregate of its own function or block scope and all the inner scopes nested within it. It can only be accessed within this lexical environment.

Example:

```javascript
function a() {
  if (true) {
    let color = "green";
  }

  function b() {
    function c() {
      console.log(color); // The 'console.log()' method call is outside the 'color' variable's lexical scope
    }
    c();
  }
  b();
}
a(); // OUTPUT: Uncaught ReferenceError: color is not defined
```

The code snippet above outputs an error message because the `console.log()` method is called outside the `color` variable's lexical scope or not nested within the `color` variable's block scope, and so has no access to this variable.

```javascript
function a() {
  if (true) {
    let color = "green";

    function b() {
      function c() {
        console.log(color); // The 'console.log()' method call is within the 'color' variable's lexical scope
      }
      c();
    }
    b();
  }
}
a(); // OUTPUT: green
```

The code snippet above runs fine without an error because the `console.log()` method is called within the `color` variable's lexical scope or nested within the `color` variable's block scope, and so has access to this variable.

## CONCLUSION

A variable's scope determines the section of a program where it can be accessed and in Javascript, there are four kinds of scope- Global scope, which spans the entire program; Block scope, which is restricted to a code block; Function scope, which is strictly restricted to a function's body and Lexical scope, defined by a variable's position in a nested sequence.

Understanding scope is important as it can help you design your code better and more importantly, make your program more secure as variables in your program can be made only accessible in certain parts of it, thus reducing the potential for malicious exploitation or accidental manipulation of data.

It is also for a similar reason, that the `let` and `const` keywords introduced in the ES6 version of JavaScript, are now usually recommended over `var` when declaring variables.

Thanks for reading.