JavaScript Scope

Scope defines where in your code a variable is visible and can be accessed.

What is scope?

Scope is the set of rules that determines where a name (a variable or function) can be referenced in your program. When JavaScript runs, it does not treat every variable as visible everywhere. Instead, each variable belongs to a region of code, and trying to use it outside that region results in an error or an unexpected value. Understanding scope is what lets you reason about which variable a name refers to and why a value is or is not available at a given point.

JavaScript has three main kinds of scope: global scope, function scope, and block scope. The keyword you use to declare a variable, along with where you place the declaration, decides which scope the variable lives in.

  • Global scope: declared outside any function or block, visible everywhere in the program.
  • Function scope: declared inside a function, visible only within that function.
  • Block scope: declared with let or const inside a { } block, visible only within that block.

Block scope with let and const

Variables declared with let and const are confined to the nearest enclosing pair of curly braces. This includes the body of an if statement, a for loop, or a standalone block. Once the block ends, the variable no longer exists. This behavior helps prevent accidental reuse of variable names and keeps temporary values contained.

Block scope in action

<!DOCTYPE html>
<html>
<body>

<h2>Block Scope</h2>

<script>
{
  let message = "inside the block";
  console.log(message); // "inside the block"
}

// console.log(message); // ReferenceError: message is not defined

if (true) {
  const limit = 10;
  console.log(limit); // 10
}
// limit is not accessible here
</script>

</body>
</html>

Function scope and var

The older var keyword does not respect block boundaries. A var declaration is scoped to the entire function that contains it, regardless of how many blocks it sits inside. This difference is a common source of bugs, which is why modern code favors let and const. The example below shows how var leaks out of a block while let does not.

var vs let inside a block

<!DOCTYPE html>
<html>
<body>

<h2>Function Scope vs Block Scope</h2>

<script>
function testScope() {
  if (true) {
    var a = 1;   // function scoped
    let b = 2;   // block scoped
  }
  console.log(a); // 1  -> var leaked out of the if block
  // console.log(b); // ReferenceError: b is not defined
}

testScope();
</script>

</body>
</html>

Nested scope and the scope chain

Scopes can be nested inside one another. When code looks up a variable, JavaScript first checks the current scope, then the scope that encloses it, and so on outward until it reaches the global scope. This lookup path is called the scope chain. An inner scope can read variables from outer scopes, but outer scopes cannot see variables declared inside inner ones.

Inner scope reading an outer variable

<!DOCTYPE html>
<html>
<body>

<h2>Nested Scope</h2>

<script>
const country = "India";

function greet() {
  const name = "Asha";
  function inner() {
    // both country and name are visible here
    console.log(name + " from " + country);
  }
  inner();
}

greet(); // "Asha from India"
</script>

</body>
</html>
KeywordScopeRedeclarableReassignable
varFunctionYesYes
letBlockNoYes
constBlockNoNo
Note: Prefer const by default, use let when you know the value will change, and avoid var in new code. Keeping variables in the smallest scope that works makes programs easier to read and less prone to bugs.

Exercise: JavaScript Scope

How is a variable declared with var scoped inside a function?