Try ModdyAI for FREE!

Create your own AI-powered moderator — no coding required. Prefer building your own tools? Use our API to integrate moderation into your workflow effortlessly.

Try for Free

Understanding JavaScript Closures: A Beginner's Guide

Published on June 9, 2025 4 min read


Cover for the article

JavaScript closures are a fundamental concept that often confuses beginners, yet understanding them deeply can elevate your coding skills. Closures arise naturally when functions return other functions, enabling inner functions to retain access to variables from their outer scopes, even after the outer function has finished executing. This concept is a cornerstone in functional programming with JavaScript and is essential for data encapsulation, event handling, and performance optimization.

Understanding Functions as First-Class Citizens in JavaScript

In JavaScript, functions are first-class citizens, meaning they behave like objects. They can be stored in variables, passed as arguments, or even returned from other functions. Consider this example:

function funOne() {
  console.log("Inside funOne function");
  function funTwo() {
    console.log("Inside funTwo function");
  }
  return funTwo;
}

const exm = funOne();
exm(); // Calls funTwo

Here, funOne returns the nested function funTwo. We store this returned function in exm and invoke it, demonstrating how functions can be passed and returned as values.

This behavior is possible because functions are objects stored on the heap with references managed via variables. When funOne is called, it creates an execution context and returns a reference to funTwo. This is the memory model that sets the stage for understanding closures.

The Execution Context and Memory in JavaScript

JavaScript manages function execution using two key memory components: the call stack and the heap. When a program runs:

Execution contexts have two phases:

  1. Creation Phase: Declarations of variables and functions are processed.
  2. Execution Phase: The code executes and variable assignments happen.

This is crucial for closures because even after the execution context for the outer function completes, memory associated with its variables can persist if the inner function retains access to them.

What Are Closures? Explaining with an Example

A closure is formed when an inner function retains access to variables of its outer (enclosing) function even after the outer function has finished execution.

Consider this code:

function outerFunction() {
  let outerVariable = 10;
  return function innerFunction() {
    console.log("Outer variable's value is", outerVariable);
  };
}

const exm = outerFunction();
exm();  // Outputs: Outer variable's value is 10

Even though outerFunction has completed execution, innerFunction still has access to outerVariable because of the closure. This happens because the inner function forms a closure over the lexical scope — the environment where the function was declared.

This concept is what prevents variables in the outer function from being garbage collected as long as the closure exists.

Practical Use Case: Building a Counter with Closures

Closures are especially useful in scenarios requiring data encapsulation and state management. Here's an example of a counter function that maintains its own count independent of other counters:

function createCounter() {
  let count = 0;
  return function () {
    count += 1;
    console.log("Count is", count);
  };
}

const counterA = createCounter();
counterA(); // Count is 1
counterA(); // Count is 2

const counterB = createCounter();
counterB(); // Count is 1
counterB(); // Count is 2

Each call to createCounter creates a new count variable scoped to that specific counter function because the inner function closes over its lexical scope. This example illustrates how closures allow for private variables and state to persist across function calls.

For more on function scopes and closures, check the MDN Web Docs on Closures.

Why Are Closures Important in JavaScript?

Closures are not just an academic concept but power several real-world JavaScript features:

Understanding closures fully prepares you to write efficient and maintainable code in JavaScript.


Mastering closures is a game-changer in JavaScript programming. They provide powerful capabilities to manage state, control access to variables, and optimize performance. Keep practicing with examples like nested functions and counters demonstrating lexical scope. If you found this explanation helpful, experiment with closures in your projects and explore the related topics on JavaScript functions and scope in official documentation. Happy coding!


This blog post is based on content from a YouTube video. Watch it here. All rights reserved by the original creator.