Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk2 min

JavaScript Closures: How Functions Keep Access to Their Surroundings

A closure lets a JavaScript function keep access to bindings from where it was created. Learn how that works, how closures share state, and why var loop callbacks can return the last value.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A JavaScript function can still access variables from where it was created, even after the outer function has finished. That continuing access is a closure: the function retains references to its surrounding lexical environment, not necessarily a frozen copy of every value.

What a closure is

MDN defines a closure as “the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).” In practical terms, when JavaScript creates a function, that function retains access to the bindings in the scope where it was defined. If the function is called later, it can still use those bindings.

As an Amazon Associate I earn from qualifying purchases.

Consider a counter factory:

function makeCounter() {
  let count = 0;
  return function () {
    count += 1;
    return count;
  };
}

const next = makeCounter();
next(); // 1
next(); // 2

Calling makeCounter() creates the count binding and returns a nested function. The outer call then finishes, but the returned function can still access and update that binding. The function does not need a new copy of count on each call; it continues to refer to the same binding.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Calling makeCounter() again creates a different environment, so the new counter has its own independent count. “Remember” is a useful shorthand for this retained access, not a claim that a function snapshots every value around it. See MDN’s JavaScript closures guide.

How closures keep state with the code that uses it

Closures are useful when a function needs to carry state into later work, such as a callback or event handler. They also let several functions created during the same outer call share one environment. For example, a factory can return increment, decrement, and read functions that all operate on the same private counter binding.

function makeCounter() {
  let count = 0;

  return {
    increment() {
      count += 1;
      return count;
    },
    decrement() {
      count -= 1;
      return count;
    },
    value() {
      return count;
    }
  };
}

const counter = makeCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.decrement(); // 1
counter.value();     // 1

Each method closes over the same count binding, which is why one method’s update is visible to the others. The variable is not exposed as a property of the returned object; callers interact with it through the provided operations. This is a lightweight way to keep data and the functions that use it together, not a complete security boundary.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Why callbacks in a var loop can all see the last value

A common closure surprise comes from callbacks created in a loop using var:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 0);
}

The callbacks run after the loop has finished. Because var is function-scoped, these callbacks all access the same i binding, which the loop has changed to 3. The callbacks therefore log 3, 3, and 3. The cause is the shared changing binding; the timer merely makes it clear that the callbacks execute later.

Use let for a per-iteration binding

For this pattern, declaring the loop variable with let gives each iteration its own binding for callbacks to access:

for (let i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 0);
}

These callbacks log 0, 1, and 2. The difference is which binding each callback closes over.

Use for...of or forEach when they fit the task

When iterating over values, for...of is another clear option:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
for (const value of values) {
  setTimeout(function () {
    console.log(value);
  }, 0);
}

For arrays, a callback passed to forEach also receives the current value as an argument:

values.forEach(function (value) {
  setTimeout(function () {
    console.log(value);
  }, 0);
});

Choose the loop form that matches the job. MDN’s JavaScript for reference explains loop lexical declarations and the shared-binding issue.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.