What is JavaScript scope & the scope chain?
Published: 2024-07-09 02:37:26

Scope is a fancy term to determine where a variable or function is available to be accessed or used. We have four types in JS - global, function, module (not discussed here) and block. 

The global scope is when you define something outside of any functions. 

```
var name = "meg"

function sayHello() {
        ...more code here
```
The variable name is not inside any function, therefore it is in the global scope, and it is available to be accessed or used anywhere down the page including inside functions. 

```
var name = "meg"

function sayHello() {
   console.log(name)
}
```
This will print out "meg" on the console. The variable name's value is accessible everywhere below the line it is declared. The next type of scope is the function scope. 

```
function sayHello() {
   var name = "meg";
   console.log(name)    // prints "meg" 
}

console.log(name)   // name is not accessible here, reference error
```
In the code above, name is declared inside the function sayHello, so name can be used from inside that function. However, if we try to access it outside the function, we can't. 

The next type of scope was introduced in es6. It is called block scope, and with it's introduction we received 'let' and 'const' both of which give us block scope. Block scope is when variables are accessible only between the curly braces for which they are declared and is specifically for code like conditional statements and loops. 

```
const names = ["Alice", "Mary", "Tom"]

function sayHelloToAll() {
for (let i =0; i < names.length; i++){
      console.log("hi," + names[i])  // prints "hi, Alice" and so on for each name.
  }
console.log(i)

}
```
The variable i is declared with let inside a for loop and is therefore scoped only to the code within the curly braces of the for loop. If we try to access i outside of the curly braces, even in the same function, we can't access it. 

You will also hear the term "local" scope, which refers to a non-global variable living within a function, aka function scope. Local scope and block scope are **_not_** the same thing. Block scope is particularly for loops and conditions. 

The scope chain simply means that when JS is interpreted (when you run the code), it will look within the function for the variable and if it can't find it locally, it will look **_upwards_** for the variable. 

```
const name = "Charlie"

function sayHello(){
  const pet = "cat";
  console.log(name)           // prints "charlie"
    function nameYourPet() {
      console.log(pet);       // prints "cat" 
      console.log(name);      // prints "Charlie"
    }
}
```
In our code above, the console log of the variable pet will look in the nested nameYourPet function and doesn't find it, so it goes up to the next level and finds it within the sayHello function. The console log of name looks within nameYourPet and doesn't find it, so it goes up to sayHello and still doesn't find it, but then it looks up in the global scope and finds it there. 

The scope chain moves **_upward_** only. 

As a new developer in 2024 it is very important to be able to discuss some of the complexities and oddities of JS for some interviews, so you should be able to talk about why var can be problematic. However, don't code with var anymore. You can do everything you need with let and const. If you or your employer do insist on still using var please turn on strict mode at the top of your js file:

`'use strict'`

and learn about IIFEs and closures as a few ways to protect your scope.

In closing let's just look at a common interview question for determining your knowledge of scope and why var is problematic. Look at the following code and explain the outcome of the console logs. 

```
// we have four button elements in the html

 const buttonArr = document.querySelectorAll('button');
  for ( var i = 0; i < buttonArr.length; i++) {
    buttonArr[i].onclick = () => console.log(`you clicked the number ${i+1} button`);
  }
```

When you use var, the console log will say you clicked the number 5. All of them will say you clicked 5 no matter which one you click. 

If you change the var to let, the console log will now correctly state if you clicked button 1, 2, 3, or 4. 

Why? Remember var is function scoped, and by the time the click event is triggered, the loop has completed and i has the value of buttonArr.length. When we switch to let we get a new i for each time through the loop. The event handler created in each iteration retains a reference to the i value from that specific iteration (it's actually a closure, but more on that some other time).