When learning JavaScript, one of the most important concepts to understand is scope. But as the language evolved, new keywords like let and const introduced a twist: block scope.

In this post, we’ll break down what scope is, what block scope means, and how to avoid common mistakes when working with variables in JavaScript.


🧠 What is scope?

Scope is the area of your code where a variable is accessible.

There are three main types of scope in JavaScript:

  • Global scope — accessible everywhere
  • Function scope — accessible only inside a specific function
  • Block scope — accessible only inside a specific block (like { })

Example of global vs function scope:

var name = 'Maria'; // Global

function greet() {
  var message = 'Hello ' + name; // Function scoped
  console.log(message);
}

greet();            // "Hello Maria"
console.log(name);  // "Maria"
console.log(message); // ReferenceError

Here, message is only accessible inside the greet function.


🔐 What is block scope?

Block scope was introduced in ES6 with let and const. It limits variable visibility to the block where it's defined (for example, inside an if or for statement).

{
  let a = 10;
  const b = 20;
  var c = 30;
}

console.log(a); // ReferenceError
console.log(b); // ReferenceError
console.log(c); // 30

  • a and b are block-scoped: not accessible outside the { }
  • c is function-scoped: still accessible because var ignores block scope

🧩 Function scope vs block scope

Let’s look at a comparison:

function test() {
  if (true) {
    var x = 1;
    let y = 2;
    const z = 3;
  }

  console.log(x); // 1
  console.log(y); // ReferenceError
  console.log(z); // ReferenceError
}

test();

Inside the if block:

  • x (declared with var) is hoisted to the function scope
  • y and z (with let and const) stay inside the if block

This is one of the key differences between var and the newer keywords.


⚠️ Common pitfall: loops

If you’ve ever written a loop and all your event listeners behave the same, block scope fixes that.

Example with var:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Output: 3 3 3

Now with let:

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Output: 0 1 2

let creates a new i for each loop iteration—problem solved.


✅ Recap

  • var is function-scoped
  • let and const are block-scoped
  • Use let and const for safer, more predictable code
  • Block scope makes it easier to avoid bugs, especially in loops and conditional blocks

📌 Conclusions

Understanding scope helps you write cleaner and less error-prone JavaScript.

Function scope was the default for years, but block scope with let and const is now the recommended way to declare variables.

If a variable only needs to live inside an if, for, or other block, use block scope—it keeps things tidy and avoids unexpected behavior.