> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/getify/You-Dont-Know-JS/llms.txt
> Use this file to discover all available pages before exploring further.

# Chapter 3: The Scope Chain

> Explore how nested scopes create a scope chain, understand shadowing, and learn how JavaScript determines variable access through the chain.

Chapters 1 and 2 laid down a concrete definition of *lexical scope* (and its parts) and illustrated helpful metaphors for its conceptual foundation. Before proceeding with this chapter, find someone else to explain (written or aloud), in your own words, what lexical scope is and why it's useful to understand.

That seems like a step you might skip, but I've found it really does help to take the time to reformulate these ideas as explanations to others. That helps our brains digest what we're learning!

## Understanding the Scope Chain

The connections between scopes that are nested within other scopes is called the **scope chain**, which determines the path along which variables can be accessed. The chain is directed, meaning the lookup moves upward/outward only.

## "Lookup" Is (Mostly) Conceptual

In the previous chapter, we described the runtime access of a variable as a "lookup," where the *Engine* has to start by asking the current scope's *Scope Manager* if it knows about an identifier/variable, and proceeding upward/outward back through the chain of nested scopes (toward the global scope) until found, if ever. The lookup stops as soon as the first matching named declaration in a scope bucket is found.

This suggestion of a runtime lookup process works well for conceptual understanding, but it's not actually how things usually work in practice.

<Note>
  The color of a marble's bucket (aka, meta information of what scope a variable originates from) is *usually determined* during the initial compilation processing. Because lexical scope is pretty much finalized at that point, a marble's color will not change based on anything that can happen later during runtime.
</Note>

Since the marble's color is known from compilation, and it's immutable, this information would likely be stored with (or at least accessible from) each variable's entry in the AST; that information is then used explicitly by the executable instructions that constitute the program's runtime.

In other words, *Engine* doesn't need to lookup through a bunch of scopes to figure out which scope bucket a variable comes from. That information is already known! Avoiding the need for a runtime lookup is a key optimization benefit of lexical scope.

However, this lookup would only be needed once per variable at most, since nothing else during runtime could later change that marble's color.

## Shadowing

"Shadowing" might sound mysterious and a little bit sketchy. But don't worry, it's completely legit!

Where having different lexical scope buckets starts to matter more is when you have two or more variables, each in different scopes, with the same lexical names. A single scope cannot have two or more variables with the same name; such multiple references would be assumed as just one variable.

Consider:

```javascript theme={null}
var studentName = "Suzy";

function printStudent(studentName) {
    studentName = studentName.toUpperCase();
    console.log(studentName);
}

printStudent("Frank");
// FRANK

printStudent(studentName);
// SUZY

console.log(studentName);
// Suzy
```

<Tip>
  Before you move on, take some time to analyze this code using the various techniques/metaphors we've covered in the book. In particular, make sure to identify the marble/bubble colors in this snippet. It's good practice!
</Tip>

The `studentName` variable on line 1 creates a RED(1) marble. The same named variable is declared as a BLUE(2) marble on line 3, the parameter in the `printStudent(..)` function definition.

What color marble will `studentName` be in the assignment statement and the `console.log(studentName)` statement? All three `studentName` references will be BLUE(2).

This is a key aspect of lexical scope behavior, called **shadowing**. The BLUE(2) `studentName` variable (parameter) shadows the RED(1) `studentName`. The parameter is shadowing the (shadowed) global variable.

### Global Unshadowing Trick

<Warning>
  Leveraging the technique I'm about to describe is not very good practice, as it's limited in utility, confusing for readers of your code, and likely to invite bugs to your program. I'm covering it only because you may run across this behavior in existing programs.
</Warning>

It *is* possible to access a global variable from a scope where that variable has been shadowed, but not through a typical lexical identifier reference.

In the global scope, `var` declarations and `function` declarations also expose themselves as properties on the *global object*. If you've written JS for a browser environment, you probably recognize the global object as `window`.

Consider this program:

```javascript theme={null}
var studentName = "Suzy";

function printStudent(studentName) {
    console.log(studentName);
    console.log(window.studentName);
}

printStudent("Frank");
// "Frank"
// "Suzy"
```

The `window.studentName` expression accesses the global variable `studentName` as a property on `window`. That's the only way to access a shadowed variable from inside a scope where the shadowing variable is present.

<Warning>
  Just because you *can* doesn't mean you *should*. Don't shadow a global variable that you need to access, and conversely, avoid using this trick to access a global variable that you've shadowed.
</Warning>

This "trick" only works for accessing a global scope variable, and only one that was declared with `var` or `function`. Other forms of global scope declarations do not create mirrored global object properties:

```javascript theme={null}
var one = 1;
let notOne = 2;
const notTwo = 3;
class notThree {}

console.log(window.one);       // 1
console.log(window.notOne);    // undefined
console.log(window.notTwo);    // undefined
console.log(window.notThree);  // undefined
```

### Copying Is Not Accessing

Consider:

```javascript theme={null}
var special = 42;

function lookingFor(special) {
    var another = {
        special: special
    };

    function keepLooking() {
        var special = 3.141592;
        console.log(special);
        console.log(another.special);  // Ooo, tricky!
        console.log(window.special);
    }

    keepLooking();
}

lookingFor(112358132134);
// 3.141592
// 112358132134
// 42
```

The `special: special` is copying the value of the `special` parameter variable into another container (a property of the same name). Of course, if you put a value in another container, shadowing no longer applies. But that doesn't mean we're accessing the parameter `special`; it means we're accessing the copy of the value it had at that moment.

### Illegal Shadowing

Not all combinations of declaration shadowing are allowed. `let` can shadow `var`, but `var` cannot shadow `let`:

```javascript theme={null}
function something() {
    var special = "JavaScript";

    {
        let special = 42;   // totally fine shadowing
        // ..
    }
}

function another() {
    // ..
    {
        let special = "JavaScript";

        {
            var special = "JavaScript";
            // ^^^ Syntax Error
            // ..
        }
    }
}
```

The real reason it's raised as a `SyntaxError` is because the `var` is basically trying to "cross the boundary" of (or hop over) the `let` declaration of the same name, which is not allowed.

<Note>
  **Summary:** `let` (in an inner scope) can always shadow an outer scope's `var`. `var` (in an inner scope) can only shadow an outer scope's `let` if there is a function boundary in between.
</Note>

## Function Name Scope

A `function` declaration looks like this:

```javascript theme={null}
function askQuestion() {
    // ..
}
```

And such a `function` declaration will create an identifier in the enclosing scope named `askQuestion`.

What about this program?

```javascript theme={null}
var askQuestion = function(){
    // ..
};
```

One major difference between `function` declarations and `function` expressions is what happens to the name identifier of the function. Consider a named `function` expression:

```javascript theme={null}
var askQuestion = function ofTheTeacher(){
    // ..
};
```

`ofTheTeacher` is declared as an identifier **inside the function itself**:

```javascript theme={null}
var askQuestion = function ofTheTeacher() {
    console.log(ofTheTeacher);
};

askQuestion();
// function ofTheTeacher()...

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

Not only is `ofTheTeacher` declared inside the function rather than outside, but it's also defined as read-only:

```javascript theme={null}
var askQuestion = function ofTheTeacher() {
    "use strict";
    ofTheTeacher = 42;   // TypeError
    //..
};

askQuestion();
// TypeError
```

## Arrow Functions

ES6 added an additional `function` expression form to the language, called "arrow functions":

```javascript theme={null}
var askQuestion = () => {
    // ..
};
```

The `=>` arrow function doesn't require the word `function` to define it. Arrow functions are lexically anonymous, meaning they have no directly related identifier that references the function.

```javascript theme={null}
var askQuestion = () => {
    // ..
};

askQuestion.name;   // askQuestion
```

<Note>
  Other than being anonymous (and having no declarative form), `=>` arrow functions have the same lexical scope rules as `function` functions do. An arrow function, with or without `{ .. }` around its body, still creates a separate, inner nested bucket of scope.
</Note>

## Backing Out

When a function (declaration or expression) is defined, a new scope is created. The positioning of scopes nested inside one another creates a natural scope hierarchy throughout the program, called the scope chain. The scope chain controls variable access, directionally oriented upward and outward.

Each new scope offers a clean slate, a space to hold its own set of variables. When a variable name is repeated at different levels of the scope chain, shadowing occurs, which prevents access to the outer variable from that point inward.

As we step back out from these finer details, the next chapter shifts focus to the primary scope all JS programs include: the global scope.
