Global Scope, Function Scope, and Block Scope

JavaScript

The Core Concept: Lexical Scope

In JavaScript, scope refers to the context in which variables and functions are declared and can be accessed. JavaScript uses lexical scoping (or static scoping), which means the scope is determined by where the variables and functions are written in the code, not by where they are called. Here is a detailed breakdown of the three types of scope, perfect for interview preparation.

Global Scope

This is the default, outermost scope. Any variable declared outside of a function or a block has global scope.

  • Accessibility: A global variable is accessible from anywhere in your JavaScript file, including inside functions and blocks.
  • A Critical Interview Point (var vs let/const): When you declare a global variable using var, it gets attached as a property to the global object. In a web browser, the global object is window. However, variables declared with let and const at the top level do not become properties of the window object. This is a key distinction.
  • Risks: Polluting the global scope is generally considered bad practice in large applications. It can lead to "naming collisions" where different scripts accidentally modify the same global variable, causing hard-to-debug errors.

Code Example:

// 'var' attaches to the window object
var globalFramework = 'React';

// 'let' and 'const' DO NOT attach to the window object
let globalVersion = 18;
const globalAuthor = 'Meta';

console.log(window.globalFramework); // Outputs: "React"
console.log(window.globalVersion); // Outputs: undefined
console.log(window.globalAuthor); // Outputs: undefined

function printGlobals() {
// All are accessible inside a function
console.log(
`${globalFramework} v${globalVersion} was created by ${globalAuthor}.`
);
}

printGlobals(); // Outputs: React v18 was created by Meta.

Function Scope

When you declare a variable inside a function, its access is limited to that function. This is known as function scope.

  • Keyword: The var keyword is function-scoped. A variable declared with var anywhere inside a function is accessible anywhere else within that same function, but not outside of it.
  • Hoisting with var: var declarations are "hoisted"โ€”meaning the declaration (but not the assignment) is conceptually moved to the top of its function scope during compilation. This means you can reference the variable before it's declared, and you'll get undefined instead of an error.

Code Example:

function prepareForInterview() {
// The 'topic' variable is hoisted here (var topic = undefined;)
console.log(topic); // Outputs: undefined (due to hoisting)

var topic = 'JavaScript Scopes';
var isReady = true;

console.log(`Today's topic is ${topic}.`); // Outputs: Today's topic is JavaScript Scopes.
}

prepareForInterview();

// Trying to access 'topic' here will cause a ReferenceError
// console.log(topic); // ๐Ÿ›‘ Uncaught ReferenceError: topic is not defined

Block Scope

This is a more granular level of scope, introduced in ES6. A block is any code wrapped in curly braces , such as in an if statement, a for loop, or even a standalone block.

  • Keywords: The let and const keywords are block-scoped. They are only accessible within the block in which they are defined.
  • Temporal Dead Zone (TDZ): Like var, let and const declarations are also hoisted. However, they are not initialized with undefined. They are in a "temporal dead zone" from the start of the block until the declaration is executed. If you try to access them in the TDZ, you will get a ReferenceError. This prevents you from accidentally using a variable before its value is set.

Code Example:

function checkScope() {
let framework = 'React'; // Function-scoped `let`
const year = 2024; // Function-scoped `const`

if (true) {
// ---- Start of Temporal Dead Zone for `newFramework` ----
// console.log(newFramework); // ๐Ÿ›‘ ReferenceError: Cannot access 'newFramework' before initialization

let newFramework = 'Vue'; // Block-scoped to the 'if' block
const newYear = 2025; // Block-scoped to the 'if' block

console.log(
`Inside the block, we are discussing ${newFramework}.`
); // Outputs: Vue
console.log(
`The outer framework is still ${framework}.`
); // Outputs: React (from the outer scope)
}

// 'newFramework' and 'newYear' are not accessible here
// console.log(newFramework); // ๐Ÿ›‘ ReferenceError: newFramework is not defined
}

checkScope();

Interview Cheat Sheet

Modern Best Practice: For clean, predictable code, always prefer const by default. Use let only for variables that you know need to be reassigned (like a counter in a loop). Avoid using var in modern JavaScript to prevent common issues with its scoping and hoisting behavior.

Featurevarletconst
ScopeFunction ScopeBlock ScopeBlock Scope
Reassignable?YesYesNo
Mutable?YesYesYes (for objects/arrays)
HoistingHoisted and initialized with undefinedHoisted, but in Temporal Dead Zone (TDZ)Hoisted, but in Temporal Dead Zone (TDZ)
Global ObjectAttaches to window objectDoes not attachDoes not attach
00:00