JS Sketchbooksee JavaScript think ✏️
← back to phase 3

3.5 — Scope

Here's a question that has quietly followed you since Phase 1: when a line of code says ship, how does the engine know which ship — and why can some lines see a variable while others act like it doesn't exist? The answer is scope: every variable lives inside a bubble, and bubbles nest inside each other like soap bubbles on paper.

The rule of the whole lesson fits in one line: inner bubbles can see outward; outer bubbles can never see in. Master that one-way glass and you'll never be surprised by "is not defined" again — and you'll be ready for closures, the most magical thing in JavaScript, two lessons from now.

watch it happen
let planet = "Earth";

function mission() {
  let ship = "Falcon";

  if (ship === "Falcon") {
    let fuel = 100;
    console.log(fuel + " left on " + ship);
  }

  console.log(ship + " from " + planet);
  console.log(fuel);
}

mission();

Three bubbles, drawn straight from the braces: the global bubble (the whole file), mission()’s bubble, and the if block’s bubble. Every { } pair blows a new bubble.

global bubbleplanetmission()shipif blockfuelconsole
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

Real names: each bubble is a scope — global scope, function scope, block scope. What we drew as a ray is the engine walking the scope chain. Current scope first, then outward, one level at a time, stopping at the first match. Exhaust the chain without a match → ReferenceError.

This is called lexical scoping: the chain is fixed by where the code is written (where the braces are), not by how it's called.

Remember leaky var from lesson 1.4? Now you can say precisely why it leaks: var ignores block bubbles and attaches to the whole function bubble. For twenty years that was all JavaScript had — real block scope only arrived with let/const in 2015.

Fun fact: the spec has a deliciously spooky name for one corner of scope. The stretch of code above a let line — where using the name throws an error instead of answering — is officially called the Temporal Dead Zone. Yes, that's the real term standards engineers use, and yes, it sounds like a sci-fi movie.

your turn

⌨️ everything at once

A store prints price tags: item, price, and the store’s name on every tag. The function reads a constant from the OUTER bubble — scope in action.

requirements:

  • The store’s name — "Code Corner" — lives in a variable named shopName, declared OUTSIDE the function. It never changes; store it accordingly.
  • A function named priceTag takes two inputs: item first, then price — and its lookup ray reaches outward to find shopName.
  • Each call prints one tag matching the expected output below exactly — built from the inputs and shopName, never typed by hand. (Copy the long dash — from the expected output; it’s not the minus key.)
  • Two tags to print: gear at 5, spring at 2.

when you press RUN, the console must show exactly:

gear — $5 (at Code Corner)
spring — $2 (at Code Corner)

✏️ Quick check 1

The lookup ray travels in ONE direction only. Type it: inward or outward.

✏️ Quick check 2

Code in the global bubble tries to read a let variable declared INSIDE a function. Type the NAME of the error it gets.

✏️ Quick check 3

Two variables, same name, different bubbles. Type exactly what calling f() prints:

let x = "out";

function f() {
  let x = "in";
  console.log(x);
}

f();
teach it back

🗣️ Now teach it back

Explain scope to a friend using the bubbles-and-ray picture: where do variables live, which direction can lookups travel, and what happens when two bubbles use the same name?

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
Every { } blows a bubble (scope). let/const variables live in the bubble where they were declared, and die when it pops.
Lookups shoot rays OUTWARD through the scope chain — inner sees outer, outer never sees in. No match anywhere → ReferenceError.
Same name in two bubbles? Nearest wins (shadowing). var ignores block bubbles — that’s exactly why lesson 1.4 called it leaky.
Fun fact: the spec really calls the region before a let line the "Temporal Dead Zone" — sci-fi name, official term.