What it does: When JavaScript can’t find a variable in current scope, it looks UP the chain (outward) through parent scopes until it finds it or reaches global scope.

The Scope Chain Hierarchy:

JavaScript looks for variables in this order:

  1. Current scope (where you are now)
  2. Parent scope (one level up)
  3. Grandparent scope (two levels up)
  4. …continues up…
  5. Global scope (final stop)
  6. ReferenceError (if not found anywhere)

What Creates New Scopes:

✅ Creates New Scope (Chain Link):

function outer() {          // New scope
    if (true) {            // New scope (block)
        for (let i = 0; i < 3; i++) {  // New scope (block)
            // Chain: for → if → outer → global
        }
    }
}

❌ Does NOT Create New Scope:

const obj = {
    name: "John",
    greet() {
        console.log(name); // Looks in: greet → global (NOT in obj!)
    }
};
// Objects don't create scope - methods are just functions

Scope Chain Examples:

Example 1: Nested Functions

const global = "I'm global";
 
function outer() {
    const outerVar = "I'm outer";
    
    function inner() {
        const innerVar = "I'm inner";
        console.log(global);    // Found in global scope
        console.log(outerVar);  // Found in outer scope
        console.log(innerVar);  // Found in current scope
    }
    
    inner();
}
// Chain: inner → outer → global

Example 2: Object Methods (Common Trap)

javascript

const name = "Global John";
 
const obj = {
    name: "Object John",
    greet() {
        console.log(name); // "Global John" (NOT "Object John"!)
    }
};
 
obj.greet(); // Looks in: greet function → global scope
// Objects don't participate in scope chain!

Example 3: Closures

javascript

function createCounter() {
    let count = 0;
    
    return function() {
        count++; // Looks in: anonymous function → createCounter → global
        console.log(count);
    };
}
 
const counter = createCounter();
counter(); // 1 (found count in createCounter scope)

Interview Gotchas:

Gotcha 1: Object properties vs variables

javascript

const x = "global x";
 
const obj = {
    x: "object x",
    method() {
        console.log(x); // "global x" (scope chain)
        console.log(this.x); // "object x" (object property)
    }
};

Gotcha 2: Block scope chain

javascript

function test() {
    const a = "function";
    
    if (true) {
        const b = "block";
        
        if (true) {
            console.log(a); // "function" (found in function scope)
            console.log(b); // "block" (found in parent block)
        }
    }
}
// Chain: inner if → outer if → function → global

Gotcha 3: Loop scope chain

javascript

function test() {
    const message = "Hello";
    
    for (let i = 0; i < 3; i++) {
        setTimeout(() => {
            console.log(message); // "Hello" (found in function scope)
            console.log(i); // 0,1,2 (found in loop block scope)
        });
    }
}
// Chain: setTimeout callback → for loop → function → global

Gotcha 4: Arrow functions and scope

javascript

const obj = {
    name: "Object",
    
    regularMethod() {
        const name = "Method";
        
        const arrow = () => {
            console.log(name); // "Method" (found in regularMethod)
        };
        
        arrow();
    }
};
// Chain: arrow function → regularMethod → global

Mental Model - The Elevator:

Think of scope chain like an elevator going UP:

javascript

function level3() {          // 3rd floor
    function level2() {      // 2nd floor  
        function level1() {  // 1st floor (current)
            console.log(x);  // Looking for x...
        }
    }
}
 
// JavaScript's search:
// Floor 1: Is x here? No
// Floor 2: Is x here? No  
// Floor 3: Is x here? No
// Ground (global): Is x here? Yes/No → Found/ReferenceError

What Participates in Scope Chain:

✅ Part of Scope Chain:

  • Functions (regular, arrow, methods)
  • Blocks ({} with let/const)
  • Global scope
  • Module scope

❌ NOT Part of Scope Chain:

  • Objects (properties)
  • Classes (properties)
  • this context
  • Prototypes

The Search Rules:

Rule 1: Lexical Scope (Where Written)

javascript

function outer() {
    const x = "outer";
    
    function inner() {
        console.log(x); // Looks where inner was WRITTEN, not called
    }
    
    return inner;
}
 
const fn = outer();
fn(); // Still finds x in outer scope

Rule 2: Scope Chain Never Goes Down

javascript

function parent() {
    function child() {
        const secret = "hidden";
    }
    
    console.log(secret); // ReferenceError - can't access child scope
}

Bottom line: Scope chain only goes UP (outward) through nested functions and blocks to find variables. Objects don’t create scope - their methods are just functions that follow normal scope rules. JavaScript searches from current scope → parent → grandparent → … → global → ReferenceError.