Free beginner tutorial

JavaScript Scope: Global, Function and Block Scope

Scope determines where a variable can be accessed in JavaScript. Understanding scope helps you avoid name conflicts and errors caused by using a value outside the place where it was declared.

What is scope?

Each declaration belongs to a scope. Code can use a variable from its own scope and, in nested code, can usually read declarations from an outer scope. Code outside that scope cannot access a local variable.

Function scope

A variable declared inside a function is available within that function, but not to code outside it:

function createMessage() {
  const message = "Your changes are saved.";
  return message;
}

console.log(createMessage());
// "Your changes are saved."

// message is not available here.

Keeping temporary values inside the function that uses them makes the rest of the program easier to understand.

Block scope with let and const

A block is code inside braces, such as the body of an if statement or a loop. Variables declared with let and const are limited to the block where they appear:

function checkStatus() {
  if (true) {
    const status = "Ready";
    let attempts = 1;
    var legacyNote = "Function scoped";
  }

  console.log(legacyNote); // "Function scoped"
  // status and attempts are not available here.
}

checkStatus();

var is function-scoped rather than block-scoped, which can make it less predictable in loops and conditionals. Prefer const when you will not reassign a variable and let when you will.

Global scope and modules

Declarations outside a function or block are available to other code in their surrounding top-level scope. In a classic script, this is often called global scope. JavaScript modules have their own top-level scope, so their declarations do not automatically become global variables.

Keep shared state limited. A function that receives what it needs through parameters is easier to reuse than one that depends on many global variables.

Nested scopes and shadowing

Nested code can read a variable from an outer scope. A declaration inside the nested block can also use the same name, which is called shadowing:

const color = "blue";

function showColor() {
  const color = "green";
  return color;
}

console.log(showColor()); // "green"
console.log(color);       // "blue"

The inner color is separate from the outer one. Although shadowing is allowed, distinct names can make code clearer when the values represent different things.

Common scope questions

Why does JavaScript say a variable is not defined?

The name may be misspelled, declared inside a different function or block, or used before its declaration is available. Check where it is declared and whether the code reading it is inside that scope.

Are let and const block-scoped?

Yes. Both are limited to the nearest enclosing block. const prevents reassignment of the binding; it does not make an object’s contents immutable.

Use local variables by default. Keeping data close to the code that uses it helps prevent accidental changes elsewhere.