Masterbook/Chapter 3• 4 min read
View Raw Code on GitHub

What is scope (global, function, block)?

What is Scope(global, function, block)?

  • Scope is the area of a program where a variable or function name is visible and can be accessed. Understanding scope helps you predict where a value can be read or changed and prevents accidental name collisions. In JavaScript there are three primary kinds of scope you will use every day: global scope, function scope, and block scope. There is also module scope in ES modules, which behaves like file level scope, but this note focuses on the everyday three.

  • Global scope means a name is available everywhere in your program after it is defined. In a browser, global variables become properties of the window object. In Node.js, the global object is different, and variables declared with let or const at the top level of a module are not added to the global object. Global scope is convenient but dangerous because any part of the program can read or change that value. Prefer limiting scope where possible.

  • Function scope is created each time a function is called. Variables declared with var inside a function are visible anywhere inside that function but not outside it. Because var is function scoped, using it inside if or for blocks does not limit its visibility to those blocks; it remains available everywhere in the function.

  • Block scope is created by a pair of braces. The most common blocks are those from if, for, while, try, and just plain braces. Variables declared with let or const are block scoped. They exist only inside that block and are not accessible outside. This prevents accidental leaks and makes code easier to reason about. Classes declared with class also follow block scoping rules. Variables in block scope have a temporal dead zone before the declaration line, which means you cannot access them before their declaration executes.

  • Shadowing happens when an inner scope declares a name that already exists in an outer scope. Inside the inner scope, the new declaration hides the outer one. Shadowing can be useful for clarity when parameter names repeat, but overusing it can reduce readability.

  • Lexical scope means that JavaScript decides which variables are visible based on where functions and blocks are written in the code, not based on where they are called at runtime. A function can access variables from the scope where it was defined. This idea is the foundation for closures.

  • Examples:

// global scope example
let siteName = "Docs";
function show() {
  console.log(siteName); // can read global
}
show();
// function scope with var
function demo() {
  var x = 1;
  if (true) {
    var x = 2; // same function-scoped variable
  }
  console.log(x); // 2
}
demo();
// block scope with let and const
function demo2() {
  let a = 1;
  if (true) {
    let a = 2; // different, block-scoped variable
    const b = 3;
    console.log(a, b); // 2 3
  }
  console.log(a); // 1
  // console.log(b); // ReferenceError
}
demo2();
// shadowing and lexical scope
const value = "outer";
function make() {
  const value = "inner";
  return function () {
    console.log(value); // reads "inner" because of lexical scope
  };
}
make()();

Common misconceptions

  1. Variables declared with var in a block are block scoped. In reality, var is function scoped and leaks out of the block.
  2. Global variables declared with let or const become properties on window. In browsers only var at the top level does that; let and const at top level of a script create global bindings but not window properties, and in modules they are module scoped.
  3. A variable defined inside a function can be accessed after the function returns. This is only possible through closures, not by direct access.

Practice questions

  1. Explain the difference between function scope and block scope using a short code example.
function funcScope() {
  // Function Scope
  var funcScopeValue = 10;
}

if (true) {
  // Block Scope
  let blockScopeValue = 20;
}
  1. Why is global scope considered risky, and how can you reduce reliance on it in a large application.
    -> Global scope is considered risky because it allows any part of your codebase to read or modify data at any time, leading to unpredictable behavior and hard-to-track bugs.

  2. What is shadowing, and when could it reduce readability.
    -> Shadowing occurs when a variable declared within a inner scope has the exact same name as a variable in an outer scope. The inner variable temporarily hides (shadows) the outer variable, making the outer variable inaccessible within that inner block.