Understanding JavaScript scope
Published: 2022-05-09 13:57:29

---
title: Understanding JavaScript scope
published: true
date: 2020-05-18 00:00:00 UTC
tags: 
canonical_url: https://carl-topham.com//articles/javascript-scope
---

Scope refers to which functions, variables and objects other functions, variables and objects are able to access when an application is run. It can seem confusing at first, but with a slightly strange example I will try and explain the basics unsing castles and emojis 🤔...

## Global and local scope

Imagine a castle. There is the land outside the castle which is `global`, and there is the land inside the castle which is `local`. People in the castle can see out into the countryside and see what exists outside in `global`, but people from `global` can't see into the castle's `local` environment.

```
let barbarian = "😈"; // Barbarians roam everywhere outside. Be careful!

function castleWalls () {
    let guard = "🥷"; // We have a few guards in the walls to protect us
    console.log([guard, barbarian]) // => ["🥷", "😈"]
}

castleWalls(); 

console.log(barbarian) // => "😈"
console.log(guard) // => `Uncaught ReferenceError: guard is not defined`

```

`barbarian` is global, and `guard` is local to the `castleWalls`. What that means is that anything within the `castleWalls` can "see" what is within itself, **and** what is on the outside.

- The `castleWalls` scope allows it to see the local `guard` AND the global `barbarian`.
- The global scope cannot see the `guard` (because they hide behind the `castleWalls`!).

## Multiple local scopes

Each function has it's own local scope but can't see into the local scope of others.

```
let barbarian = "😈";

function castleWalls () {
    let guard = "🥷";
}

function village () {
    let villager = "👩‍🌾";
    console.log(villager); // => "👩‍🌾"
    console.log(barbarian); // => "😈"
    console.log(guard); // => `Uncaught ReferenceError: guard is not defined`
}

```

Just as the barbarians cannot see into the `castleWalls`, the same applies to the `village`.

- The `village` can see the global `barbarian` and it's own local `villager`.
- The `village` cannot see into the `guard` because it is local/inside the `castleWalls`.
- The `castleWalls` is separate from the `village`, it cannot see into the `village` so it cannot see `villager`.

Essentially, everything can see out of it's own scope, but not into the scope of others, unless it is created inside of the other scope.

## Nested local scope

A bit like in Inception, there are multiple levels of local scope. Each nested code block (`for` loop, `function` etc) has it's own scope. When these are nested within each other you end up with muliple levels of of local scope.

In the following example each "area" within the castle also has it's own local scope. A castle needs a inner wall, and a tower, so let's build them. They can see outwards, but not inwards.

```
let barbarian = "😈";

function castleWalls () {
    let guard = "🥷";
    
    function innerWalls () {
        let archer = "🏹️";
    
        function tower () {
            // The king is here! Long live the king!
            let king = "🤴"
            console.log("Tower: ", [king, archer, guard, barbarian])
            // => "Tower: " ["🤴", "🏹️", "🥷", "😈"]    
        }
        
        console.log("innerWalls: ", [archer, guard, barbarian])
        // => "innerWalls: " ["🏹️", "🥷", "😈"]
        tower();
    }
  
    console.log("outerWalls: ", [guard, barbarian]);
    // => "outerWalls: " ["🥷", "😈"]
    innerWalls()
}

console.log("global: ", [barbarian]) // => "global: " ["😈"]
castleWalls();

```

- In the `tower`, the king can see (has access to the scope of) the local `tower`.
- He also can see out from the tower and into the `innerWalls` (local), the `castleWalls` (local) and into the surrounding countryside (`global`).
- In the `innerWalls`, the archers cannot see the king, but they can see the `castleWalls` and their local `guard` and can see out to the surrounding countryside (`global` scope).
- The `barbarians` can see nothing other than themselves or anything else in the `global` scope.

Because everything within a scope gains that scope for itself it means that a nested block of code will gain the scope it has been created in. `tower` gains the scope of `innerWalls` because it has been created within inner walls. This continues up the chain until you reach the `global` scope.

If you try to access `king`, `archer`, or `guard` from outside the castle you will get `Uncaught ReferenceError: king is not defined` because the global scope has no visibility inside the walls, or tower.

> Note: Luckily in these example we have ninjas on guard, so the king is safe. Long live the king! 🤴