Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

147
Views
Closure in event handler

var element = document.getElementById('test-button');

//event handler
element.onclick = (function outer() {

  var counter = 0;

  return function inner() {

    counter++;
    alert('Number of clicks: ' + counter);
  };
})();
<button id="test-button">Test</button>

I don't understand why the variable counter won't reset to 0 every time the button is clicked, or maybe when it's clicked, only the function inner() get executed, then why the variable counter get set to 0 when first click occurs. The code is from this link, after carefully read their explanation, I'm still confused.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

why the variable counter get set to 0 when first click occurs.

That is not the moment it gets set to 0. This happens when the assignment to .onclick happens. At that moment outer is defined and executed. So that is the moment counter is set to 0. No click is handled yet.

only the function inner() get executed

Indeed. outer is only executed once, when the main script is executed on page load, and then never again. inner is the function that gets assigned to onclick and thus has the role of event handler. inner has access to the counter that is defined in outer, but outer is never executed again.

outer is a so-called immediately executing function.

As a comparison: you could achieve something similar with this code:

var counter = 0;
element.onclick = function inner() {
    counter++;
    alert('Number of clicks: ' + counter);
};

...but the downside now is that counter is a global variable, that could be altered by some other code. To make sure counter is only available to the click handler, a closure is created for it, which you could also do like this:

function outer() {
    var counter = 0;
    element.onclick = function inner() {
        counter++;
        alert('Number of clicks: ' + counter);
    };
}
outer();

The downside here is that outer has a so-called side-effect: it assigns to element.onclick. This is the reason to choose to return inner and leave it to the caller of outer to do something with it, e.g. assign it to .onclick.

Then we get something like this:

function outer() {
    var counter = 0;

    return function inner() {
        counter++;
        alert('Number of clicks: ' + counter);
    };
}

element.onclick = outer();

This is essentially the same as your code: the function is first defined, and then immediately executed. The function that gets assigned to onclick is the one that is returned by outer, i.e. inner.

Yet another way to achieve this encapsulation of counter:

function inner() {
    this.counter++;
    alert('Number of clicks: ' + this.counter);
}

element.onclick = inner.bind({ counter: 0 });

Here the we provide an unnamed object that is always passed as this-argument to inner whenever it is called. As we don't retain a reference to that object outside of this construct, we achieve the same principle: the counter's state is maintained, but is not accessible outside the handler.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!