Home
 › Learn
 › JavaScript

JavaScript Scope and Closures

Understanding JavaScript Scope and Closures with Easy Examples

Updated At: October 2021
JavaScript Scope and Closures

Scope and closures are fundamental JavaScript concepts that determine how variables are accessed and managed within functions and code blocks, with scope defining the visibility and accessibility of variables in different contexts, while closures allow functions to "remember" and access variables from their outer scope even after the containing function has finished executing.

Global vs Function Scope

JavaScript variables operate within different scopes that control where they can be accessed in your code.

Global scope makes variables available everywhere in your program - you can access them from inside functions, loops, conditionals, or any other code block. For example, if you declare var userName = "John" at the top level of your script, you can use userName anywhere in your code, whether it's inside a function like function greetUser() { console.log(userName); } or within an if statement.

These global variables essentially act like a "public square" where all parts of your program can read and modify the values. In browser environments, variables declared outside any function automatically become properties of the window object, so var globalVar = "hello" becomes accessible as window.globalVar

Function scope works differently by creating isolated environments where variables are only accessible within the specific function where they're declared. Whether you use varlet, or const inside a function, they all behave similarly by remaining completely inaccessible from outside that function. For instance, if you have function,

function calculateTotal() {
  var tax = 0.08;
  let subtotal = 100;
  const discount = 10;
}

 none of these variables (taxsubtotal, or discount) can be accessed from outside the calculateTotal function - they're trapped within their function's scope boundaries.

When variables share the same name in both global and function scope, JavaScript treats them as completely separate entities - the function will use its local version while the global version remains unchanged. This scoping hierarchy allows child scopes (like functions) to access parent scope variables, but prevents the reverse, creating a structured approach to variable management that balances accessibility with code organization.

Lexical Scoping Rules

Lexical scoping, also known as static scoping, determines variable accessibility based on where variables are declared in the source code rather than where functions are called. The fundamental rule is that inner functions have access to variables declared in their outer scopes, creating a hierarchical chain where child functions can reach up to parent scopes but parents cannot access child variables. When JavaScript encounters a variable reference, it searches through the scope chain starting from the innermost scope and moving outward until it finds the variable or reaches the global scope - throwing a reference error if no matching variable exists.

This mechanism operates through lexical environments that contain two essential components: an environment record storing the actual variables and functions, and a reference to the outer environment that maintains the scope chain. The key principle is "where you write it, not where you call it" - meaning the scope is fixed at declaration time regardless of where the function is later invoked. For example, a function defined inside another function can access the outer function's variables even when called from a completely different context, enabling powerful patterns like closures where functions "remember" their lexical environment long after the containing function has finished executing.

Closure Scope Chain

Closures create powerful scope chains that extend through multiple levels of nested functions, allowing inner functions to access variables from all outer scopes simultaneously. When a nested function is created, it maintains references not just to its immediate parent scope, but to the entire chain of enclosing scopes, including the global scope. This creates a cascading effect where variables are resolved by searching from the innermost scope outward until the identifier is found

JavaScript closures operate through a systematic scope chain hierarchy that enables inner functions to access variables from multiple outer function layers and the global scope. Consider a practical example: when a function is nested three levels deep, it can access its own local variables, plus variables from all three parent functions, plus global variables - effectively creating a "stacked" environment where expressions like a + b + c + d + e can reference parameters and variables from multiple function layers simultaneously.

This powerful mechanism enables advanced JavaScript patterns such as the module pattern, where private variables can be shared among multiple functions within the same closure while remaining completely inaccessible from external code, providing true data encapsulation and privacy in JavaScript applications. The scope chain also integrates seamlessly with modern ES6+ module systems, allowing closures to capture both block-scoped variables declared with let and const, as well as module-scoped variables that persist across imports and exports, making closures essential for building scalable, maintainable JavaScript applications.

JavaScript

    React

      NextJS

        HTML

          CSS

            Sign up for our newsletter.

            Copyright © theHardCoder 2021 - 2025