Scopes: Local and Global Scope in JavaScript
The accessibility of variables, functions, and other identifiers in your code is controlled by the fundamental idea of scope. It outlines the sections of your software that are deemed “in scope” or usable by an identifier.
The scope gives the JavaScript Engine the guidelines it needs to locate variables by their identification name. It’s a component of how the Engine manages and accesses variables in conjunction with the Compiler and Scope.
Essentially, scope establishes the variables’ lifetime and visibility. “In scope” refers to the area of the program code where a variable is defined. Since variables are necessary for handling and storing data, our programs would be far more constrained without scope.
There are various scope types available in JavaScript, including:
- Global Scope: The broadest scope is the global scope. You can access variables declared in the global scope from anywhere in your JavaScript code. A variable becomes a global variable if a value is assigned to it inside of a function without the use of a declaration keyword (let, var, or const). This is generally prohibited in order to prevent “polluting the global namespace” and may result in unexpected behaviour.
- Function Scope: Local variables are those declared inside a function with var. Function parameters are only available within the body of the function and have function scope as well. These function-scoped variables are usually no longer available after the function has completed running.
- var declared inside a function “pierces through” the function’s code blocks ({}), causing it to be function-scoped as opposed to block-scoped.
- Block Scope: Code blocks encapsulated in curly braces {} are linked to this type of scope. Block scope applies to variables specified with let or const. This indicates that they can only be accessed within the block in which they are declared and any nested blocks that are part of it. Block scopes can also be produced using loops. This is a significant distinction from var, which lacks block scope.
Nested Scope and the Scope Chain: Scopes can be nested inside each other. The JavaScript Engine uses a particular lookup technique when it wants to locate a variable (a process known as variable resolution). It begins by searching the immediate, innermost scope for the variable. The Engine searches the next contained (outer) scope if the variable is not found there, and so on until it reaches the global scope. The scope chain is the name given to this hierarchical lookup structure.
// **Global Scope:**
// Variables declared outside of any function or block are in the global scope
// Global variables are accessible from anywhere in the program
let outerVariable = “I’m in the outer scope”; // This variable is in the global scope
// **Function Scope:**
// Each function you define creates a local scope
// Variables declared within a function (using let, const, or var) are typically local to that function
function outerFunction() {
// This variable is local to outerFunction’s scope.
let innerVariable = “I’m inside outerFunction”;
// **Accessing Variables from Outer Scopes:**
// Code in an inner scope can access variables from any outer scope that contains it
// This behaviour is known as **lexical scoping**
// The search for a variable starts in the current scope and proceeds upwards through the **scope chain**
console.log(outerVariable); // outerFunction can access outerVariable from the global scope.
// **Nested Functions and Nested Scope:**
// JavaScript allows functions to be nested inside other functions
function innerFunction() {
// This variable is local to innerFunction’s scope.
let deepestVariable = “I’m in the innermost scope”;
// innerFunction can access variables from its own scope:
console.log(deepestVariable);
// innerFunction can access variables from outerFunction’s scope (its immediate parent):
console.log(innerVariable);
// innerFunction can access variables from the global scope (the outermost scope):
console.log(outerVariable);
}
innerFunction(); // Call the nested function
// **Variables Are Not Accessible from Inner Scopes to Outer Scopes:**
// Variables declared within a function (like innerVariable) or a block (like deepestVariable, if using let/const)
// are typically **local** to that scope and are not accessible from outside it
// Variables declared with `let` and `const` are **block-scoped**
// while variables declared with `var` are function-scoped
// Attempting to access a variable outside its defined scope results in a **ReferenceError**
// Uncommenting the line below would cause a ReferenceError because `deepestVariable` is
// defined inside `innerFunction` and is not accessible in `outerFunction`’s scope.
// console.log(deepestVariable); // ReferenceError: deepestVariable is not defined
}
outerFunction(); // Call the outer function
// Uncommenting the line below would cause a ReferenceError because `innerVariable` is
// defined inside `outerFunction` and is not accessible in the global scope.
// console.log(innerVariable); // ReferenceError: innerVariable is not defined
JavaScript’s Lexical Scope, also known as Static Scope, is characterised by this behaviour. According to lexical scope, the scope of variables is determined by the physical writing and nesting of functions and blocks code. In order to clarify how this search operates, the authors also discuss the theoretical idea of a Lexical Environment, which has a reference to its external environment and internally holds variables.
Local and Global Scope in JavaScript
Variables defined outside of any function or code block are referred to as having global scope. After they are defined, these global variables are accessible and usable across the entire application. Global variables are those that are declared at the top level of a script with var.
On the other hand, a function declares local variables. They only apply to the function for which they are defined. Local variables are also applied to function parameters. Moreover, variables declared inside blocks using let and const have local (block-specific) scope. Within its scope, the local variable takes precedence over the global one if they have the same name. This effectively hides the global variable.
Here is an example demonstrating both:
// Global Scope:
// Variables declared outside of any function or block reside in the global scope.
// Global variables are accessible from anywhere in the program unless shadowed.
let programName = “My App”; // This variable is in the global scope.
// Function Scope:
// Each function creates its own local scope.
function displayInfo() {
// This variable is local to displayInfo’s scope.
// It has the same name as the global variable.
let programName = “Module A”; // Local variable
// Variable Shadowing:
// When a variable in an inner scope (like a function scope) has the same name
// as a variable in an outer scope (like the global scope), the inner variable
// “shadows” or hides the outer one within the inner scope
// The search for a variable starts in the current scope and proceeds outwards
// Code within the displayInfo function’s scope will find the *local* programName first.
console.log(“Inside function:”, programName); // Accesses the local variable (“Module A”)
}
// Call the function
displayInfo(); // Output: Inside function: Module A
// Outside the function scope:
// In the global scope, the local variable from displayInfo no longer exists
// The search for programName starts in the global scope and finds the *global* variable.
console.log(“Outside function:”, programName); // Accesses the global variable (“My App”)
Writing code that is clear, maintainable, and free of errors requires an understanding of scope. In accordance with the “Least Privilege” approach, you can avoid name conflicts and guarantee that variables are only used where intended by limiting where they are accessible. In contemporary JavaScript, let and const are typically preferred over var for block scope since they reduce variable visibility and prevent unexpected behaviour. The variables themselves are similar to “containers” or “named storage” that contain values.