JavaScript Scopes: Global, Function, and Block

Introduction

In JavaScript, scopes play a crucial role in organizing and accessing variables and functions. Scopes define the visibility and availability of variables and functions within certain regions of code. In this technical blog, we will explore the three types of scopes in JavaScript: global scope, function scope, and block scope. Additionally, we will discuss the concept of lexical scoping and how it influences variable access within nested scopes.

  1. Global Scope: In JavaScript, global scope refers to variables and functions that are not enclosed within any other function or block. These entities are accessible from anywhere within the program. Global variables and functions can be utilized across all functions and blocks. Let's illustrate this with an example:
// Global scope
let firstName = "John";
let lastName = "Doe";

function calculateAge() {
  // Function scope
  let birthYear = 1990;
  let currentYear = 2023;

  function isFullAge() {
    // Function scope
    let age = currentYear - birthYear;
    return age >= 18;
  }

  if (isFullAge()) {
    console.log(firstName + " " + lastName + " is full age.");
  } else {
    console.log(firstName + " " + lastName + " is not full age.");
  }
}

calculateAge();
  1. Function Scope: Every function in JavaScript creates its own scope. Variables and functions declared within a function are accessible only inside that function, which is known as function scope or local scope. These entities cannot be accessed outside their parent function. Let's consider an example to understand function scope:
function calculateAge() {
  // Function scope
  let birthYear = 1990;
  let currentYear = 2023;

  function isFullAge() {
    // Function scope
    let age = currentYear - birthYear;
    return age >= 18;
  }

  // Accessing variables within the function scope
  console.log(isFullAge());
}

calculateAge();
  1. Block Scope: Prior to ES6, scopes were created only by functions. However, with ES6, the concept of block scope was introduced. A block refers to any code enclosed within curly braces (e.g., if statements, for loops). Variables declared with let and const keywords inside a block have block scope, meaning they are accessible only within that block. On the other hand, variables declared with var have function scope, even if they are inside a block. Let's see an example:
function calculateAge() {
  // Function scope
  let birthYear = 1990;
  let currentYear = 2023;

  if (currentYear - birthYear >= 18) {
    // Block scope
    let message1 = "Adult";
    var message2 = "Access granted";
  }

  console.log(message1); // Throws an error
  console.log(message2); // Outputs "Access granted"
}

calculateAge();
  1. Lexical Scoping: Lexical scoping refers to the way variables are organized and accessed based on their placement within nested functions or blocks. A function or block sitting lexically within another scope has access to all variables and functions declared in its parent scope. This allows for hierarchical access to variables. Consider the following example:
let firstName = "John";
let lastName = "Doe";

function calculateAge() {
  // Function scope (nested within global scope)
  let birthYear = 1990;
  let currentYear = 2023;

  function isFullAge() {
    // Function scope (nested within calculateAge)
    let age = current

.