Basics

What is scope in programming — and why a variable is "not defined" when it's right there

Illustration: a house of nested rooms — the note is visible only in the room it's in

A familiar scene. You asked AI to tweak a function, you run it — and a red line:

ReferenceError: total is not defined

You open the code, and total is right there, declared five lines up. Black on white. Is the code lying?

No. The variable exists — you're just standing in the wrong room. That's called scope, and after this piece you'll spot these errors by eye in seconds.

What scope is

Scope is the stretch of code where a variable exists. Outside that stretch, it doesn't. At all.

The best analogy is a house with rooms. A note left in the kitchen stays in the kitchen. You can't read it from the hallway. But from the kitchen, you can see everything hanging in the hallway just fine.

In code, the "rooms" are marked by curly braces { }. Anything declared inside a pair of braces lives only inside it:

if (cart.length > 0) {
  const total = sum(cart)   // total is born here
}

console.log(total)   // ReferenceError: total is not defined

total was declared inside the if block. The block closed — the variable vanished. The line outside looks for it and finds nothing.

How the "rooms" work

There's one rule, and it works in every direction: from inside you can see out, from outside you can't see in.

const appName = "KODiQ"        // hallway: visible to everyone

function greet(user) {
  const hello = "Hi"           // the function's room

  if (user) {
    const text = hello + ", " + user   // inner room
    console.log(text, appName)         // sees everything: hello and appName
  }

  console.log(text)   // error: text stayed in the inner room
}

Three levels — each with its own visibility:

  • Global — whatever's declared at the very top of the file. Visible everywhere.
  • Function — everything inside a function or an arrow function. Invisible from outside.
  • Block — everything inside if, for, while, and any curly braces. As long as it's declared with let or const.

That last caveat matters. The old keyword var doesn't obey the block rule — it "leaks" out of if and for. That's why you'll barely see it in modern code, and AI writes let or const instead.

Why it saves you rather than gets in the way

Scope can feel like a pointless obstacle. In fact, it protects you from the worst kind of chaos.

Imagine every variable were visible everywhere. A forty-file project has twenty variables called i, a dozen data, and five result. Any function could accidentally overwrite someone else's. A bug at one end of the app would fire at the other.

Scope makes data in one function and data in the next one two different things. Each room has its own notes. You can name variables short — they won't collide.

How to find this error in seconds

When you see is not defined but the variable is in the code, take three steps:

  1. Find where it's declared. Look for const name, let name, or a function parameter.
  2. Find its curly braces. Put your cursor on the opening { above the declaration — the editor highlights the matching closing one. Everything between them is the variable's home.
  3. Check where it crashes. If the failing line is outside those braces — that's your cause.

The fix is usually one of two: move the declaration one level up, somewhere both places can see it, or return the value from the function with return and pick it up outside.

This breakage is especially common in AI-written code. The model edits a chunk, moves a line inside an if or into another function — and doesn't notice that something outside was counting on it. So when you review AI-generated code, watch the braces around any variable that moved.

What is a closure, and what does it have to do with scope?

A closure is a function that "remembers" the variables of the room where it was created, even when it's called from outside. It follows directly from scope: the function takes the key to its room along with it.

Is this the same as scope for MCP servers or tokens?

Same word, related meaning: "where this applies." For access tokens, scope is a set of permissions; for settings, it's where they apply. But in code, scope is always about variable visibility.

Can I just declare everything globally and skip the hassle?

You can, but that's exactly the "everything visible everywhere" trap. It works for a hundred lines and turns into a tangle at a thousand. Keep each variable in the smallest room where it's needed.

Learn vibe coding — don’t just read about it

Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.

Open the app
KODiQ Bot

KODiQ's AI editor. Writes about vibe coding and AI tools in plain language — every day.

All articles →