SKU // 55

JavaScript Scope

Scope is the set of rules that decides where a variable can be seen and used. A variable declared in one place might be visible everywhere, only inside one function, or only inside one pair of curly braces. Most "is not defined" errors are really scope questions.

// Three Kinds of Scope

Scope Created by Visible
GlobalDeclaring outside any function or blockEverywhere
FunctionDeclaring inside a functionOnly inside that function
Blocklet / const inside { }Only inside those braces

// Global Scope

const siteName = "JS Lab";   // global

function header() {
  return `Welcome to ${siteName}`;   // can see it
}

console.log(header());
console.log(siteName);                  // can see it here too
Welcome to JS Lab JS Lab

// Function Scope

Variables declared inside a function exist only while that function runs, and only inside it:

function bake() {
  const temp = 350;
  return `Oven at ${temp}`;
}

console.log(bake());   // "Oven at 350"
console.log(temp);     // ReferenceError: temp is not defined
Oven at 350 ReferenceError: temp is not defined

// Block Scope

let and const are limited to the nearest pair of curly braces, whether that is an if, a loop, or a plain block:

if (true) {
  const secret = "inside";
  console.log(secret);   // "inside"
}
console.log(secret);     // ReferenceError
inside ReferenceError: secret is not defined

// Looking Outward: The Scope Chain

When code uses a variable, JavaScript looks in the current scope first. If it is not there, it looks one level out, then the next, all the way to global. Inner code can see outer variables, but outer code can never see inner ones.

const planet = "Earth";             // global

function country() {
  const nation = "USA";             // function scope

  if (true) {
    const city = "Baltimore";       // block scope
    console.log(city, nation, planet); // sees all three
  }

  console.log(nation, planet);        // sees two
  // console.log(city);   would be a ReferenceError
}

country();
Baltimore USA Earth USA Earth
Picture It
Scopes are like nested rooms with one-way windows. From an inner room you can look out and see everything in the rooms around you. From outside, you cannot see in.

// Shadowing

If an inner scope declares a variable with the same name as an outer one, the inner one wins inside its scope. The outer variable is untouched:

const color = "blue";

function paint() {
  const color = "red";   // shadows the outer color
  return color;
}

console.log(paint());   // "red"
console.log(color);     // "blue"
red blue
Tip
Shadowing is legal but can be confusing to read. If two variables mean different things, give them different names.

// Automatically Global

If you assign a value to a variable that was never declared, JavaScript quietly creates a global variable, even when the assignment is inside a function:

function myFunction() {
  carName = "Volvo";    // no let, const, or var
}

myFunction();
console.log(carName);        // visible out here!
Volvo

This is the "automatic" declaration from JS Variables, and it is why that lesson said never to rely on it. In strict mode (JS Strict Mode), undeclared variables are not made global; the assignment throws a ReferenceError instead.

// Globals Live on window

In a browser, the global scope is the window object. A global declared with var becomes a property of window; one declared with let or const does not:

var carName = "Volvo";
let carModel = "XC60";

console.log(window.carName);
console.log(window.carModel);
Volvo undefined
Warning
Do not create global variables unless you intend to. Your globals can overwrite window's own variables and functions, and any code on the page, including other scripts, can overwrite yours. JS var/let/const shows a real example with var name.

// Why Not Make Everything Global?

let count = 0;   // global: any code anywhere can change it

function addPoint()    { count++; }
function resetScreen() { count = 0; }   // oops: reused the name for something else
Watch out
Global variables can be changed by any line in the program, so when one has the wrong value, the bug could be anywhere. Keep variables in the smallest scope that works.

// The Lifetime of a Variable

A variable's lifetime starts when it is declared. A function's local variables, including its parameters, are created each time the function starts and deleted when it finishes. That is why the same name can be used in different functions, and why a function never remembers its local values between calls:

function visit(name) {      // name is local too, like a let inside
  let count = 0;
  count++;
  return name + " visit #" + count;
}

console.log(visit("Ana"));
console.log(visit("Ana"));      // count starts over at 0
Ana visit #1 Ana visit #1

Global variables live as long as the page does: in a browser, they are deleted when you close the tab. The next section shows the one way a local variable can outlive its function.

// Scope and Closures

A function keeps access to the variables around it when it was created, even after the outer function has finished. You saw this in Function Expressions; now you know why it works:

function makeCounter() {
  let n = 0;               // private to this scope
  return () => ++n;
}

const next = makeCounter();
console.log(next(), next(), next());
1 2 3

Nothing outside can reach n directly. The only way to change it is through next(). Scope turned it into a private variable.

// Quick Check

What does this log?

let x = 1;
function test() {
  let x = 2;
  return x;
}
console.log(test(), x);
Show answer
2 1. The inner x shadows the outer one only inside test. The global x is untouched.

A variable is declared with const inside an if block. Where can it be used?

  1. Anywhere in the script
  2. Anywhere in the enclosing function
  3. Only inside that if block
  4. Only on the line it is declared
Show answer
C. let and const are block-scoped: they exist only inside the nearest pair of curly braces.

What happens?

function setup() {
  score = 10;
}
setup();
console.log(score);
Show answer
It logs 10. score was never declared, so the assignment made it an automatic global. In strict mode it would be a ReferenceError instead, which is the better outcome.

// Try It

  1. Click Open Playground and run it. Then log fnVar and blockVar from outside their scopes and read the errors
  2. Open the planet / nation / city example with its Try it Yourself button and add a fourth, deeper level
  3. Shadow a global variable inside a function and confirm the global is unchanged
  4. Build makeCounter() twice and show the two counters count independently
// Video Walkthroughs
Last updated: Oct 10, 2026, 12:53 AM ET