Understanding the scope of a variable is really a critical part of learning JavaScript. By using the variable in a place where it is not available will throw errors and/or introduce bugs.
DEFINITION
Scope of the variable defines-
In which part of the code the variable will be available.
If you want to know about variable and constant declaration in detail, check the details of declaration and initialization-
The variable scope in JavaScript has changed a lot over time. In this article, we have discussed different scopes of variables in JavaScript. We have also the discusses scope of a constant and compared all the scopes in detail.
Scope in a Nutshell
Here is a brief of the scope of a variable declared with “var” or “let“, and a constant declared with “const“-
var | let | const |
---|---|---|
Global Function | Block | Block |
NOTES
- A global scope means, places in the code which are not wrapped in any block.
- Function scope means, in the function definition wrapped in-
function someFuncNameHere() {
// variable defined here
} - Block scope means any place that is defined by wrapping in curly braces “{“(start) and “}“(end). Can be a loop, condition block, function block, etc.
{
// variable defined here
}
In the later parts of the article, we will discuss all the cases of these scopes and scope chain, in detail-
Global scope with “var“
Define a variable with “var“, and place it in the global scope, directly in the file (not in any function or other block). That variable will be accessible from anywhere.
Not only it will be accessible from anywhere, but it will also be available on the global object. In the case of a browser, the global variable is “window“, so the global variable will be available in the “window” object.
Case #1: Define a global variable
- Here we are defining a variable “bigBox” with a “var” keyword.
- Then we can access it using the variable name “bigBox” and also by using “window.bigBox”.
- This variable stays in the global scope and can be accessed from anywhere.
// Define a variable with "var" in the global scope
var bigBox = true;
console.log(bigBox);
console.log(window.bigBox);
Output:
true
true
Case #2: window property as a variable
- If we define a property in the “window” object, we can access it directly by using the property name only. Like, where we have added a property named “myCustom”
- This “window.myCustom” can be accessed from anywhere in the code, by both “window.myCustom” and “myCustom”.
// Define a value in window object
window.myCustom = 99;
console.log(myCustom);
console.log(window.myCustom);
Output:
99
99
Case #3: Variable defined in a Loop
- Here we have 2 variables in a loop. One is “i”, which is used to count the loop steps. And another one is “testVarInsideLoop”, this one is defined inside the loop.
- Both these variables are defined using “var”.
- These variables are accessible inside the loop.
- Also, outside the loop, we can access these variables. The value outside the loop will have the value that was last set inside the loop.
for (var i = 0; i < 5; i++) {
var testVarInsideLoop = i * 10;
console.log("i inside the loop: " + i);
console.log("testVarInsideLoop inside the loop: " + testVarInsideLoop);
}
console.log("i outside the loop: " + i);
console.log("testVarInsideLoop outside the loop: " + testVarInsideLoop);
Output:
i inside the loop: 0
testVarInsideLoop inside the loop: 0
i inside the loop: 1
testVarInsideLoop inside the loop: 10
i inside the loop: 2
testVarInsideLoop inside the loop: 20
i inside the loop: 3
testVarInsideLoop inside the loop: 30
i inside the loop: 4
testVarInsideLoop inside the loop: 40
i outside the loop: 5
testVarInsideLoop outside the loop: 40
Function scope with “var“
- Define a variable inside a function using “var”. Here we have defined a variable “myTestVarInFunc”, inside the function “bigBoxFunc”.
- This variable can be accessed anywhere inside the function using the variable name.
- This variable will not be added to the global scope (inside the “window” object in browser).
- This function-scoped variable can not be accessed outside the function.
function bigBoxFunc() {
var myTestVarInFunc = 100;
console.log("myTestVarInFunc inside function: " + myTestVarInFunc);
console.log("window.myTestVarInFunc inside function: " + window.myTestVarInFunc);
}
bigBoxFunc();
console.log("myTestVarInFunc outside function: " + myTestVarInFunc);
If we try to access the function scoped variable “myTestVarInFunc”, outside the function, It will throw an error-Uncaught ReferenceError: myTestVarInFunc is not defined
Output:
myTestVarInFunc inside function: 100
window.myTestVarInFunc inside function: undefined
Uncaught ReferenceError: myTestVarInFunc is not defined
Block scope with “let“
Let’s see what happens if we define a variable using “let”.
Case #1: Variable defined in the script
This is not actually a block scope example, but this is to demonstrate the basic behavior of a variable declared with “let”, in the script outside any block.
- We have variables here named “foo” and “bar”, defined using “let”. This is not inside any block, but in the script.
- We can access the variables from inside a function or any block of code.
- We can change the variable inside a function or in any other block.
let foo = 99;
let bar = 100;
function someOperation() {
// Change bar
bar = 789;
console.log("foo inside function: " + foo);
console.log("bar inside function: " + bar);
}
// Call the function
someOperation();
// Check variables in the main script
console.log("foo outside any block: " + foo);
console.log("bar outside any block: " + bar);
// Check if these varialbes are added to the global window object
console.log("window.foo: " + window.foo);
The variable defined with “let” is not added to the global object (window in the case of the browser).
Output:
foo inside function: 99
bar inside function: 789
foo outside any block: 99
bar outside any block: 789
window.foo: undefined
Case #2: Variable defined in a block
- Variable defined in a block using “let” can only be accessed inside the block.
- Any block(including a function or a loop) will have this behavior, of a variable defined with “let”.
{
let bigBoxBlock = 1007;
console.log("bigBoxBlock inside the block: " + bigBoxBlock);
}
console.log("bigBoxBlock outside the block: " + bigBoxBlock);
Output:
bigBoxBlock inside the block: 1007
Uncaught ReferenceError: bigBoxBlock is not defined
Case #3: Variable defined in a loop
- Variable defined with “let” for the iterator to run a loop can be accessed in the loop block, and also outside the loop.
- Variable defined with “let” inside a loop block, can only be accessed inside the loop block. We can not access that variable outside the loop block.
for (let i = 0; i < 5; i++) {
let testVarInsideLoop = i * 10;
console.log("i inside the loop: " + i);
console.log("testVarInsideLoop inside the loop: " + testVarInsideLoop);
}
console.log("i outside the loop: " + i);
console.log("testVarInsideLoop outside the loop: " + testVarInsideLoop);
Output:
i inside the loop: 0
testVarInsideLoop inside the loop: 0
i inside the loop: 1
testVarInsideLoop inside the loop: 10
i inside the loop: 2
testVarInsideLoop inside the loop: 20
i inside the loop: 3
testVarInsideLoop inside the loop: 30
i inside the loop: 4
testVarInsideLoop inside the loop: 40
Uncaught ReferenceError: i is not defined
Block scope with “const“
Constants defined using “const” have a block scope. So the scope is similar to the variables defined with “let”.
- Constants defined outside any block can be accessed from anywhere.
- Constants defined in the main script, outside any block are not added to the global scope(window in the case of the browser).
- Constant defined in a block(like a function or a loop or any other block) can not be accessed from anywhere else.
const foo = 99;
function someOperation() {
console.log("foo inside function: " + foo);
}
// Call the function
someOperation();
// Check constant in the main script
console.log("foo outside any block: " + foo);
// Check if these constants are added to the global window object
console.log("window.foo: " + window.foo);
// Define a block
{
const bigBoxBlock = 1007;
console.log("bigBoxBlock inside the block: " + bigBoxBlock);
}
// Check constant defined in a block
console.log("bigBoxBlock outside the block: " + bigBoxBlock);
Output:
foo inside function: 99
foo outside any block: 99
window.foo: undefined
bigBoxBlock inside the block: 1007
Uncaught ReferenceError: bigBoxBlock is not defined
Scope chain
The scope chain is Lexicaly defined. So we have to check where the function/variable is defined.
If some variable or function is used somewhere, then JavaScript looks for the definition in the same scope first. If it’s not found in the same scope, then it looks in the immediate outer scope. and then the outer scope of that, if required.
All these scope chain related information is true for variables defined with “var“, or “let” and also for constants defined with “const“.
Let’s check all possible cases of accessing a variable using lexical scope chaining-
Case #1: Variable defined in another function
Variable defined in a function can not be accessed from another function.
function firstFunc() {
console.log("Inside firstFunc");
// Try to access variable declared in firstFunc
console.log(mySecondVal);
}
function secondFunc() {
console.log("Inside secondFunc");
// Define variable
var mySecondVal = 107;
// Call firstFunc
firstFunc();
}
secondFunc();
Output:
Inside secondFunc
Inside firstFunc
Uncaught ReferenceError: mySecondVal is not defined
Case #2: Variable defined in outer function
If we have a function defined inside another function, then the variables defined in the outer function can be accessed from the function(s) defined inside it.
function secondFunc() {
console.log("Inside secondFunc");
// Define variable
var mySecondVal = 107;
function firstFunc() {
console.log("Inside firstFunc");
// Try to access variable declared in firstFunc
console.log(mySecondVal);
}
firstFunc();
}
secondFunc();
Output:
Inside secondFunc
Inside firstFunc
107
Case #3: Variable defined in both inside and outer function
If a variable is defined in the global scope and we try to access it in an inner function, then we can access it.
The variable just needs to be somewhere in the outer scope.
// Define variable
var mySecondVal = 107;
function secondFunc() {
console.log("Inside secondFunc");
function firstFunc() {
console.log("Inside firstFunc");
console.log(mySecondVal);
}
firstFunc();
}
secondFunc();
Output:
Inside secondFunc
Inside firstFunc
107
Case #4: Variable defined in all outer scope
If the variable is defined in multiple places of the lexical scope, then the variable that is in the closest scope will be used.
// Define variable
var mySecondVal = 11;
function foo() {
console.log("Inside foo");
// Define mySecondVal again
var mySecondVal = 22;
function bar() {
console.log("Inside bar");
// Define mySecondVal third time
var mySecondVal = 33;
function barInsider() {
console.log("In the barInsider function");
console.log(mySecondVal);
}
barInsider();
}
bar();
}
foo();
Output:
Inside foo
Inside bar
In the barInsider function
33