Variable Scope
- Global variables are those declared outside of a block
- Local variables are those declared inside of a block
// Initialize a global variable
var name = "Jone";
function transform() {
// Initialize a local, function-scoped variable
var name = "Doe";
console.log(name);
}
// Log the global and local variable
console.log(name);
transform();
console.log(name);
OutputJone
Doe
Jone
In the result of this example, both the global variable and the block-scoped variable end up with the same value.
This is because instead of creating a new local variable with var
, you are reassigning the same variable in the same scope.
let
and const
, however, are block-scoped. This means that a new, local scope is created from any kind of block, including function blocks, if
statements, and for
and while
loops.
// Initialize a global variable
let name = "Jones";
if (fullMoon) {
// Initialize a block-scoped variable
let species = "Doe";
console.log(`My name is ${name}.`);
}
console.log(`My name is ${name}.`);
Output:
My name is Jones
My name is Doe
In this example, the name variable has one value globally (Jones), and another value locally (Doe
).
Block scope
Generally, whenever you see curly brackets {}
, it is a block. It can be the area within the if
, else
, switch
conditions or for
, do while
, and while
loops.
while (/* condition */) {
// “while” block scope
const message = ‘Hi’;
console.log(message); // ‘Hi’
}
console.log(message); // => throws ReferenceError
Note: var is not block scoped
Example:
if (true) {
// “if” block scope
var count = 0;
console.log(count); // 0
}
console.log(count); // 0
Function scope
A function in JavaScript defines a scope for variables declared using var
, let
and const
.
function run() {
// “run” function scope
var message = ‘Run, Forrest, Run!’;
console.log(message); // ‘Run, Forrest, Run!’
}
run();
console.log(message); // throws ReferenceError
Scopes can be nested
In the following example the function run()
creates a scope, and inside an if
condition code block creates another scope:
function run() {// “run” function scopeconst message = ‘Run, Forrest, Run!’;if (true) {// “if” code block scopeconst friend = ‘Bubba’;console.log(message); // ‘Run, Forrest, Run!’}console.log(friend); // throws ReferenceError}run();
The scope contained within another scope is named inner scope. In the example, if
code block scope is an inner scope of run()
function scope.
The scope that wraps another scope is named outer scope. In the example, run()
function scope is an outer scope to if
code block scope.
Note: The inner scope can access the variables of its outer scope.
Lexical scope
function outerFunc() {// the outer scopelet outerVar = 'I am from outside!';function innerFunc() {// the inner scopeconsole.log(outerVar); // 'I am from outside!'}return innerFunc;}const inner = outerFunc();inner();
Look at the last line of the snippet inner()
: the innerFunc()
invokation happens outside of outerFunc()
scope. Still, how does JavaScript understand that outerVar
inside innerFunc()
corresponds to the variable outerVar
of outerFunc()
?
The answer is due to lexical scoping.