Question

JavaScript Variable Scope: Global, Function, and Block Scope

javascriptfunctionvariablesscopevar

Question

What is the scope of variables in JavaScript? Do variables declared inside a function have the same scope as variables declared outside it? Does the declaration location matter? Also, where are variables stored when they are declared globally?

Short Answer

You will learn how JavaScript decides where a variable can be accessed, how function and block boundaries affect visibility, and why global variables should be used carefully. You will also understand the difference between a global binding and a property on the browser's global object.

Concept

Variable scope is the part of a program where a variable name is available. JavaScript uses lexical scope, meaning scope is determined by where code is written, not by where a function is called.

The main scopes are:

  • Global scope: declared outside functions and blocks. It can be accessed by code in the same script or module, subject to module rules.
  • Function scope: variables declared with var, let, or const inside a function are available only in that function and its nested functions.
  • Block scope: variables declared with let and const inside {} are available only inside that block. Blocks occur in if, for, while, and similar statements.
  • Module scope: top-level declarations in an ES module belong to that module, not to every script on the page.

An inner scope can read variables from its outer scopes. An outer scope cannot directly read variables declared in an inner scope. This protects local details, prevents accidental name conflicts, and makes functions easier to understand.

const siteName = "Docs"; // global scope

function showPage() {
  const pageName = "Scope"; // function scope
  console.log(siteName);     // works: inner code can read outer variables
  console.log(pageName);     // works
}

showPage();
console.log(siteName); // works
// console.log(pageName); // ReferenceError: pageName is not defined

Mental Model

Think of scope as nested rooms in a building.

  • A global variable is a notice in the building lobby. People in rooms can read it.
  • A function variable is a note inside one room. People outside that room cannot see it.
  • A block-scoped variable is a note inside a smaller locked area within the room.

Code inside a room can look outward through the building for a name. It cannot look into a different room or a locked inner area.

Take Quiz

Syntax and Examples

Declare variables with const by default, let when reassignment is needed, and avoid var in new code unless maintaining older code.

const appName = "Task List"; // global scope

function createTask(title) {
  const status = "open"; // function scope

  if (title.length > 0) {
    const message = `Created: ${title}`; // block scope
    console.log(message);
  }

  console.log(status);
}

createTask("Buy milk");
console.log(appName);

// console.log(status);  // Error: status is only inside createTask
// console.log(message); // Error: message is only inside the if block

Here, appName is declared outside the function, so createTask can read it. status exists for the entire createTask call. message exists only while execution is inside the if block.

Step by Step Execution

Consider this code:

const currency = "USD";

function formatPrice(price) {
  const label = "Price";

  if (price > 0) {
    const formatted = `${label}: ${price} ${currency}`;
    return formatted;
  }

  return "Invalid price";
}

console.log(formatPrice(25));

Execution steps:

  1. JavaScript creates the global currency binding with the value "USD".
  2. JavaScript stores the formatPrice function so it can be called later.
  3. formatPrice(25) creates a new function scope for this call. Its price parameter is 25.
  4. label is created inside the function scope.
  5. The condition price > 0 is true, so JavaScript enters the if block.
  6. formatted is created in the block scope. It can read label from the function scope and currency from the global scope.
  7. The function returns "Price: 25 USD".
  8. The function and block scopes are no longer accessible after the call finishes. The global currency remains available while its global environment remains active.

Real World Use Cases

  • Configuration: an application may keep a small amount of shared configuration, such as an API base URL, in module-level scope.
  • Function parameters: a validation function keeps input values local so unrelated code cannot change them.
  • Loop variables: let creates a block-scoped loop variable, which helps event handlers keep the correct value.
  • Temporary values: calculations inside an if block can use local variables without exposing them to the rest of the function.
  • Reusable modules: a module can keep helper functions and internal state private while exporting only its public API.
function isValidEmail(email) {
  const hasAtSign = email.includes("@");
  return hasAtSign;
}

console.log(isValidEmail("sam@example.com"));
// hasAtSign is not accessible here
Take Quiz

Real Codebase Usage

Developers use scope to limit what each part of a program can access.

Prefer local variables

Keep a value in the smallest scope that needs it.

function calculateTotal(items) {
  let total = 0;

  for (const item of items) {
    total += item.price;
  }

  return total;
}

Use guard clauses

A guard clause returns early when input is invalid. Variables stay local to the function.

function getDisplayName(user) {
  if (!user) {
    return "Guest";
  }

  return user.name;
}

Keep module internals private

In an ES module, only exported names are intended for other files to use.

const defaultTimeout = 5000;

export function requestOptions() {
  return { timeout: defaultTimeout };
}

Other modules can import requestOptions, but cannot directly access defaultTimeout unless it is exported.

Avoid accidental globals

Strict mode and ES modules reject assignments to undeclared names, helping catch typos early.

"use strict";

function save() {
  // result = "saved"; // ReferenceError: result is not defined
  const result = "saved";
  return result;
}

Common Mistakes

Expecting a local variable outside its function

function greet() {
  const message = "Hello";
}

// console.log(message); // ReferenceError

Declare the variable outside the function only if multiple parts of the program genuinely need it. Otherwise, return the value.

function greet() {
  return "Hello";
}

console.log(greet());

Using var when block scope is intended

var is function-scoped, not block-scoped.

if (true) {
  var userRole = "admin";
}

console.log(userRole); // "admin"

Use const or let to keep the value inside the block.

if (true) {
  const userRole = "admin";
}

// console.log(userRole); // ReferenceError

Creating globals accidentally

In non-strict older scripts, assigning to an undeclared name can create a global property. This is error-prone.

function update() {
  // count = 1; // Do not do this
}

Always declare names with const, let, or, when necessary, var.

Shadowing an outer variable unintentionally

An inner declaration can hide an outer variable with the same name.

const status = "online";

function checkStatus() {
  const status = "offline";
  return status;
}

This is legal, but choose distinct names when it makes code clearer.

Assuming every global is window.someName

In a classic browser script, a top-level var often creates a property on window. Top-level let and const do not. In ES modules, top-level declarations are module-scoped instead. Prefer explicit module imports and exports rather than relying on global-object properties.

Comparisons

Declaration or locationScopeCan be reassigned?Notes
const value = 1Current block, function, or module/global lexical environmentNoThe binding cannot be reassigned; object contents may still change.
let value = 1Current block, function, or module/global lexical environmentYesUse when the variable must receive a new value.
var value = 1Current function, or global scope if outside a functionYesNot block-scoped; avoid in new code.
Function parameterCurrent functionYesLocal to each function call.
ConceptKey difference
Global scopeShared broadly and can increase coupling between unrelated code.
Function scopeExists for one function call and is useful for function-local work.
Block scopeExists only inside {} and helps prevent leaking temporary values.
Module scopeTop-level names are isolated to one module unless explicitly exported.
Take Quiz

Cheat Sheet

// Global or module-level binding
const appVersion = "1.0";

function example(input) {
  // Function scope
  let result = input;

  if (result > 0) {
    // Block scope
    const message = "Positive";
    return message;
  }

  return "Not positive";
}
  • JavaScript uses lexical scope: where code is written determines what it can access.
  • Inner scopes can access outer variables; outer scopes cannot access inner variables.
  • Use const by default.
  • Use let when reassignment is required.
  • let and const are block-scoped.
  • var is function-scoped and can escape if or loop blocks.
  • Function parameters are local to that function call.
  • Avoid mutable globals; pass values as parameters or use module exports when possible.
  • In browser classic scripts, top-level var may become window properties. Top-level let and const do not.
  • ES module top-level declarations are module-scoped.

FAQ

What is variable scope in JavaScript?

Scope defines where a variable name can be read or changed. It determines which code can access that variable.

Can a function access a global variable in JavaScript?

Yes. A function can access variables from its outer, global scope unless a local variable with the same name shadows it.

Can code outside a function access variables declared inside it?

No. Function-local variables are not directly accessible outside that function. Return a value if outside code needs the result.

Is let function-scoped in JavaScript?

No. let is block-scoped. When declared inside a function but not inside a smaller block, it is available throughout that function.

Is var block-scoped?

No. var is function-scoped. A var declared inside an if block is still available elsewhere in the containing function.

Where are global variables stored in JavaScript?

JavaScript keeps global bindings in its global environment. In browser classic scripts, top-level var commonly also appears on the window global object. Top-level let and const do not become window properties, and ES module declarations are scoped to the module.

Should I use global variables?

Use them sparingly. Globals can be changed from many places and can conflict with other names. Prefer local variables, parameters, and module imports/exports.

Take Quiz

Mini Project

Description

Build a small order-summary function that demonstrates function scope, block scope, and safe access to an outer configuration value. This mirrors how applications calculate and format data without exposing temporary implementation details.

Goal

Create a function that returns a readable order summary while keeping calculation variables local.

Requirements

  • Declare a currency constant outside the function.
  • Create a createOrderSummary function that accepts an item name and price.
  • Return an error message when the price is not greater than zero.
  • Use a block-scoped variable to format a valid price.
  • Return a summary string that includes the item name, formatted price, and currency.
Take Quiz

Keep learning

Related questions

View more