JavaScript Closures Explained with Examples (2026)

Header image: JavaScript Closures, a code editor showing makeCounter returning an arrow function that keeps incrementing its private count variable: 1, then 2.

Hey friends,

A JavaScript closure is a function bundled together with references to the variables around it, so it can still read and change those variables after the outer function has returned. MDN's Closures guide puts it as a function plus its lexical environment, and notes closures are created every time a function is created.

Closures sit under the Objects, Functions, and Classes section of the Salesforce JavaScript Developer exam (25%, the biggest section), in the objective about analyzing variable scope and execution flow. Here's how they work, with examples you can paste into the console.

What is lexical scope?

Lexical means the scope is decided by where you write the code, not where you call it. An inner function can see variables declared in the functions that wrap it.

lexical.js
1function outer() {
2  const name = 'Nick';
3  function inner() {
4    console.log(name); // inner can see outer's variable
5  }
6  inner();
7}
8outer(); // Nick

Nothing surprising yet. The closure part is what happens when inner outlives outer.

What is a simple closure example in JavaScript?

Return the inner function instead of calling it. The returned function keeps a live reference to count, even though makeCounter already finished:

counter.js
1function makeCounter() {
2  let count = 0;
3  return function () {
4    count += 1;
5    return count;
6  };
7}
8
9const a = makeCounter();
10const b = makeCounter();
11a(); // 1
12a(); // 2
13b(); // 1  (each call to makeCounter gets its own count)

Two things to notice. The closure holds a reference to the variable, not a copy of its value, so changes stick. And every call to the outer function creates a fresh scope, so a and b don't share state.

What are closures used for?

UseWhat the closure keeps
Private state (module pattern)Variables nobody outside can touch, only the returned functions
Function factoriesA setting baked in, like makeAdder(5) returning a function that adds 5
Event handlers and callbacksValues from when the handler was set up
MemoizationA cache object shared across calls
Debounce and throttleThe timer ID between calls
privateState.js
1function createAccount(opening) {
2  let balance = opening;          // private
3  return {
4    deposit(amt) { balance += amt; return balance; },
5    getBalance() { return balance; },
6  };
7}
8
9const acct = createAccount(100);
10acct.deposit(50);   // 150
11acct.balance;       // undefined: no direct access

Modern classes also have truly private fields (#balance), but closures are still the classic answer and show up in exam scenarios.

Cert Lab by Nick Frates

Let the JavaScript Developer Cert Lab test you to success

Scope, closures, hoisting, this and classes: scenario questions for every exam section, each option explained.

Start the JavaScript Developer Cert Lab for $9.99 →

Not ready to buy? Try a free lesson and see how fast you learn.

Why does var in a loop break closures?

This is the closure question everyone meets. With var, there's one i for the whole function, and every callback closes over that same variable. By the time the timers fire, the loop is done and i is 3.

loopBug.js
1for (var i = 0; i < 3; i++) {
2  setTimeout(() => console.log(i), 0);
3}
4// 3, 3, 3
5
6for (let j = 0; j < 3; j++) {
7  setTimeout(() => console.log(j), 0);
8}
9// 0, 1, 2

let is block-scoped, and a for loop creates a new binding for each iteration, so each callback gets its own j. MDN calls this a common mistake from before let existed, and shows the older fix: an extra function factory. For why the timers wait until the loop finishes, see my event loop guide.

Where do closures show up in Salesforce work?

All over Lightning web components: a debounced search handler keeps its timer ID in a closure, and arrow functions inside a component method keep this pointing at the component. If you're coming from Apex, which has no closures, this is one of the bigger mindset shifts. My LWC basics guide shows where JavaScript fits in a component.

debounce.js
1function debounce(fn, ms) {
2  let timerId;                       // kept by the closure
3  return (...args) => {
4    clearTimeout(timerId);
5    timerId = setTimeout(() => fn(...args), ms);
6  };
7}
8
9const search = debounce((term) => console.log('search', term), 300);

What closure mistakes should you avoid?

  • Using var in loops with callbacks. Use let.
  • Expecting a copy of the value. A closure sees the variable's current value when it runs, not the value when it was created.
  • Holding big objects by accident. A long-lived closure keeps everything it references alive, which can leak memory in single-page apps.
  • Creating functions inside a hot loop or constructor when a shared one would do. MDN notes methods belong on the prototype unless they need private state.

A bit about how I study. Focus on Force was my favorite resource on the way to 17 Salesforce certs. I started the traditional way, reading the study guide first and testing second, but rapid-fire practice tests are what actually made things stick. That's the loop Cert Lab is built on: quick questions, then explanations with current links, then go again.

FAQ

What is a closure in JavaScript, in one sentence?

A function that remembers the variables from the scope where it was created, even after that scope has finished running.

Is every JavaScript function a closure?

Technically every function closes over its surrounding scope when it's created. The term usually means a function that uses outer variables after the outer function has returned.

What's the difference between scope and closure?

Scope is the set of variables code can see. A closure is a function carrying that scope with it.

Are closures on the Salesforce JavaScript Developer exam?

Yes, through the objective on analyzing variable scope and execution flow. My JavaScript Developer study guide covers every section.

Where should you go next?

Nick Frates, a senior Salesforce developer with 17 certifications, built the JavaScript Developer Cert Lab at nickfrates.com: rapid-fire practice questions for every exam section, each answer explained.

Cert Lab by Nick Frates

Let the JavaScript Developer Cert Lab test you to success

Lessons, flashcards, a quiz for each of the seven exam sections and full practice exams, every answer explained.

Start the JavaScript Developer Cert Lab for $9.99 →

Not ready to buy? Try a free lesson and see how fast you learn.

Hope this helps!

Best,

Nick

Keep reading

See all posts →

Salesforce Saturdays

Join 1,033 Salesforce pros getting one 10-minute tip on Salesforce tech or career growth every Saturday.