Scope in JavaScript
Introduction
Before diving deeper, let’s clearly define what scope means in practice:
Scope answers one simple question: “From where can I access this variable?”
If you understand where a variable is accessible and where it is not, you understand scope.
The Three Core Scopes in JavaScript
In this section, we will discuss about Global, Function, Block and Lexical scope.
1. Global Scope
Definition: Global scope is the outermost scope. Any variable declared outside a function or block belongs to the global scope and is accessible anywhere in the file.
Key points:
- Exists for the lifetime of the program
- Overuse can cause conflicts
var in Global Scope
var gVar = 10; // Re-declare var gVar = 20; // allowed // Reassign gVar = 30; // allowed console.log(gVar); // 30
Behavior:
- Global variable
- Can be re-declared
- Can be reassigned
- Attached to global object
let in Global Scope
let gLet = 10; // Reassign gLet = 20; // allowed // Re-declare // let gLet = 30; // not allowed console.log(gLet); // 20
Behavior:
- Global variable
- Cannot be re-declared in same scope
- Can be reassigned
- Not attached to global object
const in Global Scope
const gConst = 10; // Reassign // gConst = 20; // not allowed // Re-declare // const gConst = 30; // not allowed console.log(gConst); // 10
Behavior:
- Global variable
- Cannot be re-declared
- Cannot be reassigned
2. Function Scope
Definition: Function scope means variables declared inside a function are accessible only within that function.
Key points:
- Created when the function runs
- Destroyed after execution
var in Function Scope
function exampleVar() { var a = 10; // Re-declare var a = 20; // allowed // Reassign a = 30; // allowed console.log(a); // 30 } exampleVar(); // console.log(a); // not accessible
Behavior:
- Scoped to function
- Can be re-declared
- Can be reassigned
let in Function Scope
function exampleLet() { let b = 10; // Reassign b = 20; // allowed // Re-declare // let b = 30; // not allowed console.log(b); // 20 } // console.log(b); // not accessible
Behavior:
- Scoped to function
- Cannot be re-declared in same scope
- Can be reassigned
const in Function Scope
function exampleConst() { const c = 10; // Reassign // c = 20; // not allowed // Re-declare // const c = 30; // not allowed console.log(c); // 10 } // console.log(c); // not accessible
Behavior:
- Scoped to function
- Cannot be re-declared
- Cannot be reassigned
3. Block Scope
Definition:
Block scope refers to variables declared inside {} such as if, for, or while blocks.
Key points:
- Introduced with ES6
- Prevents variable leakage
var in Block Scope
if (true) { var x = 10; } console.log(x); // accessible
Behavior:
- Does not respect block boundaries
- Leaks outside the block
let in Block Scope
if (true) { let y = 10; console.log(y); // accessible } // console.log(y); // not accessible
Behavior:
- Exists only inside the block
- Can be reassigned inside the block
const in Block Scope
if (true) { const z = 10; console.log(z); // accessible } // console.log(z); // not accessible
Behavior:
- Exists only inside the block
- Cannot be reassigned
Combined Example (Global + Function + Block Together)
// Global scope var gVar = "global var"; let gLet = "global let"; const gConst = "global const"; function scopeTest() { // Function scope var fVar = "function var"; let fLet = "function let"; const fConst = "function const"; if (true) { // Block scope var bVar = "block var"; // function-scoped let bLet = "block let"; // block-scoped const bConst = "block const"; // block-scoped console.log(gVar); // accessible console.log(gLet); // accessible console.log(gConst); // accessible console.log(fVar); // accessible console.log(fLet); // accessible console.log(fConst); // accessible console.log(bVar); // accessible console.log(bLet); // accessible console.log(bConst); // accessible } console.log(bVar); // accessible (var ignores block) // console.log(bLet); // not accessible // console.log(bConst); // not accessible } scopeTest(); // console.log(fVar); // not accessible // console.log(fLet); // not accessible // console.log(fConst); // not accessible
This single example demonstrates:
- Global variables are accessible everywhere
- Function-scoped variables are accessible only inside the function
varignores block scopeletandconstrespect block scope
Lexical Scope (How Access Is Decided)
Definition: Lexical scope means that variable access is determined by where the code is written, not where it is executed.
In JavaScript, functions remember the scope in which they were defined.
const globalValue = "global"; function outer() { const outerValue = "outer"; function inner() { console.log(globalValue); // accessible console.log(outerValue); // accessible } inner(); } outer();
Key points:
- Inner scopes can access outer scopes
- Outer scopes cannot access inner scopes
- Scope is fixed at write-time, not run-time
Scope Chain
Definition: When a variable is accessed, JavaScript looks for it through a chain of scopes called the scope chain.
Search order:
- Current scope
- Parent scope
- Global scope
- Error if not found
const a = "global"; function first() { const b = "function"; function second() { const c = "block"; console.log(a); // found in global scope console.log(b); // found in function scope console.log(c); // found in local scope } second(); } first();
Key points:
- JavaScript never looks downward into child scopes
- The search stops as soon as the variable is found
Shadowing (Same Name, Different Scope)
Definition: Shadowing occurs when a variable declared in an inner scope has the same name as a variable in an outer scope.
let value = "global"; function test() { let value = "function"; // shadows global value console.log(value); // function } test(); console.log(value); // global
Key points:
- Inner variable hides the outer one
- Does not modify the outer variable
- Legal with
letandconst
Summary
JavaScript Variable Summary: Scope, Reassignment, Redeclaration
| Feature | var | let | const |
|---|---|---|---|
| Scope type | Function scope | Block scope | Block scope |
Accessible outside block {} | Yes | No | No |
| Accessible outside function | No | No | No |
| Global scope behavior | Becomes global object property | Does NOT attach to global object | Does NOT attach to global object |
| Hoisting | Yes (initialized as undefined) | Yes (Temporal Dead Zone) | Yes (Temporal Dead Zone) |
| Reassignment allowed | Yes | Yes | No |
| Redeclaration in same scope | Yes | No | No |
| Block-level isolation | No | Yes | Yes |
| Safe for loops | No (leaks variable) | Yes | Yes |
| Default recommendation | Avoid | Use when mutable | Use by default |
Reassignment vs Redeclaration (Quick Reference)
| Operation | var | let | const |
|---|---|---|---|
| Reassign value | Allowed | Allowed | Not allowed |
| Redeclare in same scope | Allowed | Not allowed | Not allowed |
| Modify object/array contents | Allowed | Allowed | Allowed |
| Rebind reference | Allowed | Allowed | Not allowed |

