JavaScript Tutorial
JavaScript Scope
A name is visible in its block or function. Inner code can read outer names. Outer code cannot read inner ones.
Where a name is visible
Scope is the region of the program where a binding can be used. Declare let totalinside a function and the rest of the page cannot read total. That is not a bug — it keeps names from colliding.
Modern JavaScript uses block scope for let andconst: the name lives between the nearest curly braces. var is function-scoped and leaks out of if and for blocks. Preferlet and const.
Block scope
An if, a for, or a bare { } is a block. Alet inside it is gone when the block ends.
Example
const label = "outer";
if (true) {
const label = "inner";
console.log(label);
}
console.log(label);
The inner label shadows the outer one only inside the if. After the block, the outer name is still "outer". Two different bindings, same spelling.
Click Try it in JavaScript under an example. That opens/javascript/try — a live page and a console.
Function scope
Parameters and names declared inside a function belong to that function. Each call gets its own bindings. Inner functions can read outer names; that is a closure when the inner function outlives the call, but the rule is the same on day one: look outward, never inward.
Example
function greet(name) {
const message = "Hello, " + name;
return message;
}
console.log(greet("Ada"));
After greet returns, name and message are not available to the caller. Trying console.log(message) here would throwReferenceError.
Inner can read outer
Nested code looks up the chain: block, then function, then the next outer function, then the script (global). The first match wins.
Example
const tax = 0.2;
function priceWithTax(amount) {
function addTax() {
return amount + amount * tax;
}
return addTax();
}
console.log(priceWithTax(10));
addTax never declares amount or tax. It reads them from the function and from the script. That is legal. The reverse is not.
Outer cannot read inner
A name declared inside a function or block does not exist outside. The engine does not “remember” it for you on the next line.
Example
function total() {
const sum = 3 + 4;
return sum;
}
console.log(total());
try {
console.log(sum);
} catch (err) {
console.log(err.name + ": " + err.message);
}
Return the value you need, or declare the name in the outer scope before the inner code assigns it. Do not expect inner locals to leak.
Global names
A let or const at the top of a script is global to that script — every function on the page can read it. That is convenient for a tiny example and messy in a larger page: two scripts can fight over the same spelling.
| Kind | Visible where |
|---|---|
Block (let/const) | Inside { } |
| Function | Inside that function, including nested functions |
| Script / global | The whole file, unless shadowed |
Keep names as local as you can. Pass values in as parameters and send results out withreturn.
What to remember
letandconstlive in the block where they are declared.- Inner code can read outer names. Outer code cannot read inner ones.
- A returned value is how data leaves a function.
- Shadowing: the inner name hides the outer one until the block ends.
Next: this — a name that is not a declaration, but a value that depends on how the function was called.