CodeOath
← All posts
JavaScript75 min total · 15 parts

JavaScript Core Concepts: Scope, Closures, `this`, and the Event Loop

Contents — Part 2 of 15: Scope: Global, Function, and Block
Part 2 of 15 · ~1 min

Scope: Global, Function, and Block

Scope determines where a variable is visible. JavaScript has three layers of it:

let globalVar = "I'm everywhere"; // global scope — visible in the whole file/module

function outer() {
  let functionVar = "I'm inside outer()"; // function scope — visible anywhere inside outer, including nested functions
  if (true) {
    let blockVar = "I'm inside this if-block only"; // block scope — visible only within { }
  }
  console.log(blockVar); // ReferenceError — blockVar doesn't exist out here
}

var is function-scoped (it ignores block boundaries entirely); let and const are block-scoped (confined to the nearest enclosing { }, whether that's an if, a for loop, or a bare block). This single difference explains a huge number of surprises:

function example() {
  if (true) {
    var x = 1;
    let y = 2;
  }
  console.log(x); // 1 — var ignores the block, it's scoped to the whole function
  console.log(y); // ReferenceError — y is scoped to the if-block only
}

Nested scopes can read variables from any enclosing scope (this is called the scope chain) but not the reverse — an outer scope can never see a variable declared inside an inner one.