A variable is not reachable everywhere. The language marks out a zone of validity for every name, and outside that zone the name simply does not exist.
This boundary is not red tape. It is what lets two functions written by two different people both use a variable called total without ever getting in each other's way.
Definition
Scope is the region of code in which a declared name is reachable. JavaScript recognizes three of them, from the widest to the narrowest.
- Global scope: anything declared outside every function and every block. Inside a module, that scope stays private to the file.
- Function scope: the body of a function. It is the only one var knows about.
- Block scope: anything between braces, including an if or a for. This is what let and const use.
const site = "believemy"; // module scope
function display() {
const message = "hello"; // function scope
if (message.length > 3) {
let detail = "!"; // block scope
console.log(site + " " + message + detail);
}
// console.log(detail); // ReferenceError: outside the block
}
display(); // believemy hello!The scope chain
When the engine meets a name, it looks in the current scope, then in the surrounding one, and so on up to the global scope. The first match wins and the search stops there.
const level = "global";
function outer() {
const level = "outer";
function inner() {
console.log(level); // outer, found one step up
}
inner();
}
outer();
console.log(level); // globalThe search only ever moves outward, never inward: from outer, the variable declared inside inner is invisible. That chain, captured by a function, is what produces a Closure.
Declaring a name that already exists in an enclosing scope shadows it locally, leaving the original untouched. Handy, but a source of confusion when the two variables stand for different things.
What it changes day to day
- Declare close to the use. A variable that lives for three lines reads effortlessly.
- Stay out of the global scope. A global name can be overwritten by any code in the program.
- Watch out for a
varinside a block. It escapes and stays visible across the whole function. - A module file is already a scope. Nothing leaves it without an explicit export.
Frequently asked questions
Does a variable without a keyword become global?
In a classic script, yes: writing total = 5 with no keyword creates a global property reachable from the entire program. It is one of the costliest accidents in the language. In strict mode, and therefore in every module, the same line throws an error, which is far preferable.
How is scope different from Hoisting?
Scope answers the question "where is this name reachable", hoisting answers "starting when". The two combine: a let variable is scoped to its block, and inside that block it stays unreadable until its declaration line has run.
Does a scope really disappear at the end of the block?
Usually yes, and the memory is reclaimed. Unless a function declared inside is still referenced elsewhere: it then keeps the variables it uses alive. That is exactly how closures work, and the reason a counter can hold its value between two calls.