Scope answers “Where can I use this name?”
A variable’s scope is the part of a program where its name is available. Scope helps you keep temporary values close to the code that needs them. It also explains a common debugging surprise: a variable works on one line but produces an error on another. You can try the examples in a browser’s developer console or in a JavaScript environment that supports ES2015 or newer syntax. No libraries or setup are required.
JavaScript looks for a name in the current scope first. If it does not find one, it looks outward through surrounding scopes. Consider: const color = "blue"; function showColor() { console.log(color); } showColor(); The function can read color because color is in its surrounding scope. The reverse does not work automatically: a variable created only inside a function is not available outside it.
Function scope keeps values inside a function
A function creates a scope for its parameters and for variables declared inside it. For example: function greet(name) { const message = "Hello, " + name; return message; } console.log(greet("Sam")); Both name and message are available while greet runs. Trying console.log(message) after the function call produces a ReferenceError because message belongs to the function’s scope.
The older declaration keyword var is function-scoped, too. A var declared anywhere inside a function is available throughout that function, rather than only inside a nearby pair of braces. Its declaration is processed before the function runs, although its assignment stays where it was written. That is why reading a var before its assignment can return undefined. This behavior can hide mistakes, so let and const are usually clearer choices for new code.
Block scope follows braces
A block is a section enclosed in braces, such as the body of an if statement or a for loop. Variables declared with let or const belong to the block where they are declared. Try: if (true) { const status = "ready"; console.log(status); } The console.log inside the braces prints ready. A console.log(status) after the closing brace produces a ReferenceError. This lets you use a name for a short task without leaving it available to unrelated code.
Compare that with: if (true) { var result = "ready"; } console.log(result); If this code runs inside a function, result remains available after the if block because var follows the function scope, not the if block. In a for loop, let also gives each iteration its own binding. That distinction matters when a function created during a loop uses the loop variable later: with let, it can retain the value from its particular iteration.
Nested scopes can share or shadow names
An inner scope can read a variable from an outer scope unless it declares a variable with the same name. For example: const label = "outer"; if (true) { const label = "inner"; console.log(label); } console.log(label); The first log prints inner, and the second prints outer. The inner declaration shadows the outer one; it does not replace it. When a value seems unexpected, check whether the same name was declared closer to the line using it.
Functions can also keep access to their surrounding variables after the outer function has returned. Consider: function makeCounter() { let count = 0; return function () { count += 1; return count; }; } const next = makeCounter(); Calling next() twice returns 1 and then 2. The returned function retains access to count through a closure. Count is not available by name outside makeCounter, but the returned function can still use it.
Choose a declaration and test its boundaries
Use const when you do not need to assign a new value to a variable, and let when you do. Both are block-scoped. A const declaration does not make an object’s contents unchangeable; it prevents assigning a different value to that variable. You may still encounter var in older code, so recognize its function-scoped behavior even if you generally choose let or const for new work.
One useful debugging exercise is to predict each console.log before running a small example. Mark the braces around functions and blocks, then find the nearest declaration of each name. Also pay attention to order: using a let or const variable before its declaration produces a ReferenceError, even within the same block. If a value is needed only inside a block, declare it there. If several parts of a function need it, declare it in their shared enclosing scope. Keeping scope as narrow as practical makes code easier to follow.



