Mastering JavaScript Closures: From Free Variables to Real-World Use Cases

This article explains free variables, defines closures in ECMAScript, shows why every function is a closure, and provides practical examples—including common interview pitfalls and solutions—illustrating how closures capture and preserve lexical scope in JavaScript.

JavaScript
JavaScript
JavaScript
Mastering JavaScript Closures: From Free Variables to Real-World Use Cases

Before discussing closures, we first understand free variables.

A free variable is a variable used inside a function that is neither a parameter nor a local variable of that function.

Example:

let a = 1;

function foo() {
  console.log(a);
}

foo();

In this code, a is a free variable for foo because it is not a parameter or a local variable.

What is a Closure

In ECMAScript, a closure is a function that can access free variables.

Because every function retains the lexical environment in which it was created, all functions can be considered closures. The following code demonstrates this:

let a = 1;

function foo() {
  console.log(a);
}

foo(); // > 1

(function () {
  let a = 2;
  foo(); // > 1
})();

ECMAScript uses lexical (static) scoping, meaning the scope chain is saved when the function is created. In the example, foo was created when a was 1, so it logs 1 even when called later.

All functions also have access to the global free variable global ( window in browsers ), so every function is a closure.

Closures in Practice

Practically, a closure is a function that references a free variable, and that variable persists together with the function after the surrounding context is destroyed.

Example:

function foo(){
  let a = 1;
  return function(){
    console.log(a);
  }
}

foo();

The returned anonymous function references the free variable a; even after foo finishes, the inner function (the closure) still has access to a.

Closures keep referenced free variables from being garbage‑collected, which can increase memory usage but also enables powerful patterns. For instance:

let foo = function() {

  let a = 1;

  return {
    add: function(){
      return ++a;
    },
    sub: function(){
      return --a;
    }
  }
}

let f = foo();
f.add(); // 2
f.sub(); // 1

Interview example – using var in a loop:

let data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0](); // 3
data[1](); // 3
data[2](); // 3

All three functions capture the same free variable i, which after the loop ends has the value 3, so each call logs 3.

To output 0, 1, 2 we can create a closure that captures the current value of i:

let data = [];

for (var i = 0; i < 3; i++) {
  data[i] = (function(x) {
    return function () {
      alert(i);
    };
  })(i); // pass current i
}

data[0](); // 0
data[1](); // 1
data[2](); // 2
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptclosureIIFEFree VariableLexical Scoping
JavaScript
Written by

JavaScript

Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.