When you define a function, it creates a scope.
Everything defined within the function is not accessible by code outside the function. Only code within this scope can see the entities defined inside the scope.
function foo() {
var a = 'hello';
console.log(a); // => 'hello'
}
console.log(a); // reference error
Nested functions are possible in JavaScript and the same rules apply.
function foo() {
var a = 'hello';
function bar() {
var b = 'world';
console.log(a); // => 'hello'
console.log(b); // => 'world'
}
console.log(a); // => 'hello'
console.log(b); // reference error
}
console.log(a); // reference error
console.log(b); // reference error
When JavaScript tries to resolve a reference or variable, it starts looking for it in the current scope. If it cannot find that declaration in the current scope, it climbs up one scope to look for it. This process repeats until the declaration has been found. If the JavaScript parser reaches the global scope and still cannot find the reference, a reference error will be thrown.
var a = 'hello';
function foo() {
var b = 'world';
function bar() {
var c = '!!';
console.log(a); // => 'hello'
console.log(b); // => 'world'
console.log(c); // => '!!'
console.log(d); // reference error
}
}
This climbing behavior can also mean that one reference may "shadow" over a similarly named reference in the outer scope since it gets seen first.
var a = 'hello';
function foo() {
var a = 'world';
function bar() {
console.log(a); // => 'world'
}
}
The way JavaScript resolves scoping also applies to the const
keyword. Declaring a variable with the const
keyword implies that you are not allowed to reassign the value, but declaring it in a function will create a new scope and with that a new variable.
function foo() {
const a = true;
function bar() {
const a = false; // different variable
console.log(a); // false
}
const a = false; // SyntaxError
a = false; // TypeError
console.log(a); // true
}
However, functions are not the only blocks that create a scope (if you are using let
or const
). let
and const
declarations have a scope of the nearest block statement. See here for a more detailed description.