Scope Chain: How JavaScript Locates Variables
Before diving into the concept of the scope chain and its significance in programming, it’s essential to talk about the fundamental idea of “scope.”
What is scope?
If you google the scope meaning, you will find something like ‘the extent of the area or subject matter that something deals with or to which it is relevant,’ but what does it mean in programming?
In programming, the term ‘scope’ refers to the region or context in a program where a variable, function, or other programming elements are defined and accessible. The scope determines where in the program the variable or function can be used and accessed.
There are three types of scope in Javascript:
Global Scope
Variables or functions declared in the global scope are accessible throughout the entire program. They can be accessed from any part of the code, including inside functions or blocks.
Example of a variable in global scope:
var globalVar = 10;
function someFunction() {
console.log(globalVar); // Accessing the global variable inside the function
}
someFunction(); // Output: 10
Function Scope
Variables declared inside a function have function scope, which means they are only accessible within that function and not visible outside.
Example of a variable in function scope:
function someFunction() {
var localVar = 5;
console.log(localVar);
}
someFunction(); // Output: 5
// Trying to access the local variable outside its scope will result in an error
// console.log(localVar); // This will raise an error
Block Scope (Introduced in ES6):
Before ES6, JavaScript only had global and function scope. With ES6, the let
and const
keywords were introduced, which allow for the creation of variables with block scope. Variables declared with let
and const
are only accessible within the block in which they are defined (e.g., inside loops or conditional statements).
Example of a variable in block scope:
function someFunction() {
if (true) {
let blockVar = 20;
const anotherBlockVar = 30;
console.log(blockVar); // Accessible inside the block
console.log(anotherBlockVar); // Accessible inside the block
}
// Trying to access the block variables outside the block will result in an error
// console.log(blockVar); // This will raise an error
// console.log(anotherBlockVar); // This will raise an error
}
someFunction();
Using block scope with let
and const
helps prevent variable leaks and unintended side effects. It also allows for better control over variable lifetimes and helps avoid variable name conflicts.
In summary, both block scope and function scope are types of local scope in JavaScript. Variables defined within these scopes have limited visibility and are confined to the block or function where they are declared. They are not accessible outside of their respective scopes.
What is scope chain?
So, after explaining what scope is, and which types exists, it’s time to talk about scope chain. The scope chain is a fundamental concept in JavaScript that governs how variables are looked up and resolved during the execution of code. It refers to the hierarchical structure, which enables JavaScript to find and access variables in the correct order.
When a variable is referenced within a function or block, JavaScript searches for the variable in the current scope. If the variable is not found in the current scope, it continues to search in the parent scope, and this process continues until the variable is found (reaching the global scope) or an error occurs if the variable is not defined at all.
Let’s go through the example step by step to see how the scope chain works:
let simpleVar = "I am on global scope";
function someFunction() {
let simpleVar = "I am on function scope";
if (true) {
let simpleVar = "I am on block scope";
console.log(simpleVar); // Output: "I am on block scope"
}
console.log(simpleVar); // Output: "I am on function scope"
}
someFunction();
console.log(simpleVar); // Output: "I am on global scope"
- The variable
simpleVar
is declared in the global scope and assigned the value "I am on global scope." - Inside the
someFunction
function, another variablesimpleVar
is declared in the function scope and assigned the value "I am on function scope." This variable shadows the globalsimpleVar
within the function scope, but the globalsimpleVar
remains unaffected outside the function. - Inside the
if
block withinsomeFunction
, yet another variablesimpleVar
is declared in block scope and assigned the value "I am on block scope." This variable shadows both the function-scopedsimpleVar
and the globalsimpleVar
within the block scope. - When
console.log(simpleVar)
is called inside theif
block, it refers to the block-scopedsimpleVar
, and thus it prints "I am on block scope." - After the
if
block, whenconsole.log(simpleVar)
is called again, it refers to the function-scopedsimpleVar
, and it prints "I am on function scope." - Finally, outside the
someFunction
function,console.log(simpleVar)
refers to the globalsimpleVar
, and it prints "I am on global scope."
In this example, we can observe how variables with the same name in different scopes (global, function, and block) can coexist without interfering with each other due to the scope chain. The innermost block scope takes precedence over the function scope, which, in turn, takes precedence over the global scope for variable resolution.
Conclusion
The scope chain is essential in programming, particularly in languages like JavaScript, because it determines how variables are accessed and resolved during the execution of code. Understanding the scope chain is crucial for several reasons: variable resolution, encapsulation, avoiding name conflicts, garbage collection, and things like closures.
Properly understanding and managing the scope chain is crucial for writing reliable, maintainable, and bug-free code, as it ensures that variables are accessed in the appropriate context and that code behaves as expected.