scope refers to the visibility or accessibility of variables, functions, and objects in a particular part of the code. The scope determines the lifetime of a variable, i.e., the duration for which the variable remains accessible or visible within the program.
JavaScript has 4 types of scope:
Block scope
Function scope
Global scope
Module Scope
Global Scope
Variables declared Globally (outside any function/curly braces) it is considered Global Scope. Global variables can be accessed from anywhere in a JavaScript program. Variables declared with var
, let
and const
is quite similar when declared outside a block.
var globalVar = "This is a global variable";
function myFunction() {
console.log(globalVar);
}
myFunction(); // Output: This is a global variable
This global access makes writing code easier at first since we don't have to worry about variables being blocked by different scopes, but as we start to write more complex code. it makes difficult to manage and even more worse when you have multiple files.<script src="script-1.js"></script> <script src="script-2.js"></script>
//script-1.js
let x = 1;
//script-2.js
console.log(x); // 1
As here we can see that in above examples variable x is defined in script-1.js
and we are able to use that variable in script-2.js
this is because due to the variable defined in script-1.js is global i.e., it can be used anywhere in the program. this makes it difficult to track global variable as code becomes more complex.
Module Scope
Module scope is very similar to global scope, but with one minor difference. any variable or function declared with the let
, const
, or class
keywords is scoped to the module, meaning it is not visible outside of the module.In order to enter module scope you need to use type="module"
on your script tags.
<script src="script-1.js" type="module"></script>
<script src="script-2.js" type="module"></script>
// script-1.js
let x=1;
console.log(x); //1
// script-2.js
console.log(x); // Throws Uncaught Reference Error: a is not defined
let's take another example
// module.js
let x = 10;
function foo() {
console.log(x);
}
export { foo };
In this code, the variable x
and the function foo()
are scoped to the module.js
file and are not visible outside of it. The export
keyword is used to make the foo()
function available to other modules that import this file.
Other modules can import this file and use the exported function as follows:
// app.js
import { foo } from './module.js';
foo(); // outputs 10
In this code, the foo()
function defined in the module.js
file is imported and used in the app.js
file. Because x
is not exported, it is not accessible from the app.js
file.
Block Scope
Variables declared inside a block are only accessible within that block, and not outside of it. This means that if you try to access a block-scoped variable outside of the block you will get a reference error.
{
let x = 10; // block-scoped variable
console.log(x); // 10
}
console.log(x); // ReferenceError: x is not defined
In this example, x
is defined within a block enclosed by curly braces. The first console.log(x)
statement successfully outputs 10 because x
is in scope. However, when we try to access x
outside of the block, we get a reference error because it is not defined in that scope.
function test() {
const funcVar = "Func"
if (true) {
const ifVar = "If"
console.log(funcVar, ifVar)
// Prints: "Func", "If"
}
console.log(funVar, ifVar)
// Throws Uncaught Reference Error: ifVar is not defined
}
In this exapmle, a function named test()
is defined. Within this function, a constant variable funcVar
is declared and assigned a value of "Func".
Then, an if statement is used to define a block scope. Within this block, another constant variable ifVar
is declared and assigned a value of "If". The values of both variables funcVar
and ifVar
are printed using console.log()
statement, which results in output: "Func", "If".
However, when the console.log()
statement is called again outside the if block, it throws an Uncaught Reference Error
since ifVar
was declared within the if block and hence is not accessible outside it.
This is an example of how block scope works in JavaScript. Any variables declared inside a block using let
or const
keywords are only accessible within that block and not outside it.
Function Scope
variables declared using the var
keyword within a function have function scope, which means they are only accessible within that function and not outside it.
function test() {
var funcVar = "Func"
if (true) {
var ifVar = "If"
console.log(funcVar, ifVar)
// Prints: "Func", "If"
}
console.log(funVar, ifVar)
// Prints: "Func", "If"
}
it is the same example given in block scope but one small change made a big difference in output. here we are using var
instead of const
to define our variables.here the var
keyword ignores block level scope so even though ifVar
is defined within our if
block it doesn't matter for function scope.
another example
function myFunction() {
var message = "Hello, World!";
console.log(message); // Outputs "Hello, World!"
}
myFunction();
console.log(message); // Throws Uncaught ReferenceError: message is not defined
In the above code snippet, a function named myFunction()
is defined. Within this function, a variable named message
is declared and assigned a value of "Hello, World!". The value of message
is then printed using console.log()
statement, which outputs "Hello, World!".
However, when the console.log()
statement is called again outside the function, it throws an Uncaught Reference Error
since message
was declared within the function and hence is not accessible outside it.
This shows that variables declared using var
inside a function have function scope, which means they are only accessible within that function and not outside it.
Multiple Variables With The Same Name
One important thing to understand about scoping and how it works when you have multiple variables with the same name.
function test() {
const a = "Func"
if (true) {
const a = "If"
console.log(a)
// Prints: "If"
}
console.log(a)
// Prints: "Func"
}
in this example, the same variable name is defined in both inside our test() function and inside our if block. when we console logged a
in the if block we got a value of a
defined in if scope. again when we console logged a
outside an if block we got the value defined in test
scope.
above with same example, const is replaced with var then output will change
function test() {
var a = "Func"
if (true) {
var a = "If"
console.log(a)
// Prints: "If"
}
console.log(a)
// Prints: "If"
}
Since var
has function scope, not block scope, the variable a
declared inside the if block actually modifies the value of the variable a
declared outside the if block. So, when console.log(a)
is called outside the if block, it prints the value of "If"
, not "Func"
.
What is the Scope chain?
The scope chain is the mechanism by which JavaScript determines which variables are accessible in a particular portion of the code. When a variable is accessed in a particular portion of the code, JavaScript looks for the variable in the current scope. If the variable is not found in the current scope, JavaScript looks for the variable in the outer scope, and this process continues until the variable is found or the global scope is reached.
for example
let a = 10;
function myFunction() {
let b = 20;
function innerFunction() {
let c = 30;
console.log(a + b + c);
}
innerFunction();
}
myFunction(); // 60 (10+20+30)
In this code, a
has global scope and can be accessed anywhere in the code. b
has local scope and can only be accessed within myFunction
. c
has block scope and can only be accessed within innerFunction
.
When innerFunction
is executed, it tries to access a
, b
, and c
. Since c
is defined within innerFunction
, it can be accessed directly. b
is defined within myFunction
, so JavaScript looks for it in the outer scope of innerFunction
, which is myFunction
, and it is found there. a
is defined in the global scope, so JavaScript looks for it in the outer scope of myFunction
, which is the global scope, and it is found there.