Skip to main content

Scope, Lexical Environment, Execution Context

JavaScript's scopes, lexical environments, and execution contexts are important concepts to master for efficient coding. This post aims to demystify them and enhance your coding expertise.

Scope

Scope refers to the context where values and expressions are visible or accessible to the program. In JavaScript, scope controls the availability of variables and functions at various parts of your code.

Global Scope

Variables declared in the global scope are accessible from anywhere in the code. When you declare a variable outside any function or block, it belongs to the global scope.

let foo = "Accessible everywhere!"; 
function display() {
console.log(foo); // Outputs: Accessible everywhere!
}

Function Scope

Each function in Javascript creates a new Scope. Variables declared within a function are local to that function and cannot be accessed from outside of it. This helps prevent naming conflicts between variables with the same name in different functions.

function fn() {
const foo = "Hello, World!";
console.log(foo); // Outputs: Hello, World!
}

fn();
console.log(foo); // Error: foo is not defined

Block Scope

Block Scope was introduced in ES6. It allows you to declare variables using the let and const keywords within code blocks like if statements, for loops, or while loops. Variables declared with let and const are only accessible within the curly braces {} of the block they are defined in. This provides a more granular level of control over variable visibility and helps prevent unintended side effects in your code.

if (true) {
let foo = "I am inside a block!";
console.log(foo); // Outputs: I am inside a block!
}
console.log(foo); // Error: blockScopedVar is not defined

Scope Chain

When JavaScript tries to find a variable, it follows the scope chain. This chain starts with the current scope (where the variable is being referenced) and then moves outward to enclosing scopes. It keeps searching until it finds the variable or reaches the global scope.

Example:

let globalVar = "I'm global!";

function outerFunction() {
let outerVar = "I'm outer!";

function innerFunction() {
let innerVar = "I'm inner!";
console.log(globalVar); // Accessing global variable
console.log(outerVar); // Accessing outer variable
console.log(innerVar); // Accessing inner variable
}

innerFunction();
}

outerFunction();

Lexical Environment

A lexical environment in JavaScript is a data structure that stores the variables and functions that are defined in the current scope and all of the outer scopes. It is also known as the lexical scope or the lexical closure.

Lexical environment consists of two parts:

  • Environment Record. This record stores the variables and functions that are directly declared within the current scope (like a block of code or a function).
  • A reference to the outer environment. This reference points to the lexical environment of the enclosing scope. This creates a chain that allows functions to access variables from their outer scopes, even if those variables are no longer in the current scope itself.

Lexical environments play a crucial role in understanding how closures work in JavaScript. Closures are functions that can access variables from their outer scopes, even after the outer function has returned. This is because the closure remembers the lexical environment it was created in, giving it access to those variables.

Execution Context

The JavaScript Execution Context is the environment where code runs. It contains information about variables, functions, objects, the scope chain, and this value.

Two types of execution context

There are two main types of execution context:

  • Global Execution Context (GEC). This is the default or base execution context in which any JavaScript code starts executing when it loads in the browser or a Node.js environment.
  • Function Execution Context (FEC). Every time a function is called, a new execution context is explicitly created for that function. This context includes the local variables, parameters, and the function itself. The value of this within each function execution context depends on how the function was invoked (for example, it might refer to a global object, a specific object if called a method, or a new object if the function is a constructor).

Two stages of execution context

Each execution context has two stages:

  • Creation Phase: In this phase, the JavaScript engine parses the code, allocates memory for variables and functions, and creates the scope chain.
  • Execution Phase: Here, the actual code execution happens line by line. Statements are evaluated and executed based on the available variables and functions within the current context.

Summary

  • Javascript has 3 types of Scope: global, function, and block scope.
  • Scope Chain determines how JavaScript searches for a variable when referenced. It's essentially a hierarchy that dictates where JavaScript looks for a variable when it's used. When JavaScript searches for a variable, it starts in the current scope and continues up to the parent scope until it reaches the Global Scope.
  • A Lexical Environment is a data structure that stores the variables and functions defined in the current and outer scopes. It consists of two parts: the Environment Record and the reference to the outer Environment.
  • Execution Context is the environment where code runs. It contains information about variables, functions, objects, the scope chain, and this value.

References