Block Scoping
What is Block Scoping?
Block scoping means variables are limited to the block {} in which they are declared. let and const provide block scope, while var provides function scope.
Try Block Scoping
Code Editor
Console Output
Click "Run" to execute your code...
Example 1: Basic Block Scope
// Block scope with let and const
{
let blockLet = 'I am block scoped';
const blockConst = 'Me too';
var blockVar = 'I leak out!';
console.log(blockLet); // I am block scoped
console.log(blockConst); // Me too
console.log(blockVar); // I leak out!
}
// console.log(blockLet); // ReferenceError
// console.log(blockConst); // ReferenceError
console.log(blockVar); // I leak out! (var is not block-scoped)
// Multiple blocks
{
let x = 1;
console.log(x); // 1
}
{
let x = 2; // Different variable!
console.log(x); // 2
}Example 2: Block Scope in if Statements
let message = 'outer';
if (true) {
let message = 'inner'; // New variable, shadows outer
console.log(message); // inner
}
console.log(message); // outer
// With var (no block scope)
var count = 10;
if (true) {
var count = 20; // Same variable!
console.log(count); // 20
}
console.log(count); // 20 (modified by if block)
// Practical example
function checkAge(age) {
if (age >= 18) {
let status = 'adult';
console.log(status); // adult
}
// console.log(status); // ReferenceError
if (age >= 18) {
var statusVar = 'adult var';
console.log(statusVar); // adult var
}
console.log(statusVar); // adult var (var leaks out!)
}
checkAge(20);Example 3: Block Scope in Loops
// Classic var problem in loops
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log('var:', i), 100);
}
// Output: var: 3, var: 3, var: 3
// Fixed with let (block scope)
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log('let:', j), 100);
}
// Output: let: 0, let: 1, let: 2
// Each iteration gets its own 'j'
for (let k = 0; k < 3; k++) {
const multiplied = k * 2;
console.log(multiplied); // 0, 2, 4
}
// console.log(k); // ReferenceError
// console.log(multiplied); // ReferenceError
// Array iteration
const numbers = [1, 2, 3, 4, 5];
for (let num of numbers) {
const squared = num * num;
console.log(squared); // 1, 4, 9, 16, 25
}
// console.log(num); // ReferenceError
// console.log(squared); // ReferenceErrorExample 4: Block Scope in switch Statements
function getDayMessage(day) {
switch(day) {
case 'Monday': {
let message = 'Start of week';
console.log(message);
break;
}
case 'Friday': {
let message = 'End of week'; // Different variable!
console.log(message);
break;
}
default: {
let message = 'Middle of week';
console.log(message);
}
}
// console.log(message); // ReferenceError
}
getDayMessage('Monday'); // Start of week
getDayMessage('Friday'); // End of week
getDayMessage('Wednesday'); // Middle of week
// Without block scope (var problem)
function getDayMessageVar(day) {
switch(day) {
case 'Monday':
var messageVar = 'Start of week';
console.log(messageVar);
break;
case 'Friday':
// var messageVar = 'End of week'; // SyntaxError: already declared
messageVar = 'End of week';
console.log(messageVar);
break;
}
console.log(messageVar); // Accessible outside switch!
}Example 5: Practical Block Scoping Patterns
// Pattern 1: Temporary variables
function processArray(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
// Temporary calculation in block scope
{
const doubled = arr[i] * 2;
const squared = doubled * doubled;
result.push(squared);
}
// doubled and squared are not accessible here
}
return result;
}
console.log(processArray([1, 2, 3])); // [4, 16, 36]
// Pattern 2: Configuration blocks
function setupEnvironment(env) {
if (env === 'development') {
const API_URL = 'http://localhost:3000';
const DEBUG = true;
console.log('Dev mode:', API_URL, DEBUG);
} else if (env === 'production') {
const API_URL = 'https://api.example.com';
const DEBUG = false;
console.log('Prod mode:', API_URL, DEBUG);
}
// API_URL and DEBUG are not accessible here
}
setupEnvironment('development');
// Pattern 3: Error handling with block scope
function parseData(data) {
try {
const parsed = JSON.parse(data);
const validated = validate(parsed);
return validated;
} catch (error) {
const message = `Parsing failed: ${error.message}`;
console.error(message);
return null;
}
// parsed, validated, error, message not accessible here
function validate(obj) {
return obj && typeof obj === 'object' ? obj : null;
}
}
parseData('{"name": "John"}');Key Points
- let and const are block-scoped (limited to {} blocks)
- var is function-scoped, not block-scoped
- Block scope applies to: if, for, while, switch, try-catch, and standalone blocks
- Each loop iteration with let creates a new binding
- Block scoping helps prevent variable leakage and naming conflicts
- Use const by default, let when reassignment is needed, avoid var