-1

I have declared a divHandler fn which is then get attached to the onclick event.

After reading about closures, I understand that divHandler would have access to the enclosing environment which in this case is a function which gets attached to the onload event. So divHandler should have access to cnt var which is initialized to 0.

But when I click execute the div I get Uncaught reference error: cnt is not defined

I don't understand how can this be possible? Please help me with this. Thanks.

<script>
function divHandler(e){
    ++cnt;
    document.getElementById("d1_cnt").innerHTML=" clicked "+ cnt + " times...";
}   
window.onload=function() {
        var cnt=0;
        document.getElementById("d1").onclick=divHandler;
    }
</script>

<body>
  <div id="d1">Div click me</div><span id="d1_cnt"></span>
</body>
tintin
  • 5,676
  • 15
  • 68
  • 97

3 Answers3

3

Because cnt is a local variable in the function you're assigning to onload, and divHandler doesn't close over it. It's just like this:

function foo() {
    var a = 42;
}
// Can't access `a` here.

Instead, move cnt out to where divHandler can close over it — but don't make it a global if you don't have to:

(function() {
    var cnt = 0;

    function divHandler(e){
        ++cnt;
        document.getElementById("d1_cnt").innerHTML=" clicked "+ cnt + " times...";
    }   
    window.onload=function() {
        document.getElementById("d1").onclick=divHandler;
    }
})();

Note that the scoping function I've put around that code also makes divHandler no longer global, as (barring something you haven't shown) there's no reason for it to be.

Or actually, you could just put it all in your onload:

window.onload=function() {
    var cnt = 0;

    function divHandler(e){
        ++cnt;
        document.getElementById("d1_cnt").innerHTML=" clicked "+ cnt + " times...";
    }   

    document.getElementById("d1").onclick=divHandler;
};

Side note: The window.load event happens very late in the page loading cycle, after all images and other external resources are fully loaded (or have failed). You don't need to wait that long to hook up your click handler. Just make sure your script element is below the markup for the elements you want it to work with in your HTML, and you can hook up the handler right away. The usual recommendation is to put scripts just before the closing </body> tag, since that means they can access everything above them.

<body>
  <div id="d1">Div click me</div><span id="d1_cnt"></span>
  <script>
    (function() {
        var cnt = 0;

        function divHandler(e){
            ++cnt;
            document.getElementById("d1_cnt").innerHTML=" clicked "+ cnt + " times...";
        }   

        document.getElementById("d1").onclick=divHandler;
    })();
  </script>
</body>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Scope is based on where variables / functions are declared not where they are assigned.

var cnt scopes the variable to the (anonymous) function that it is defined within.

The function divHandler is not declared inside that function, so it has no access to that variable.

Move the divHandler function declaration inside the anonymous function expression.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

I see you have missed understanding

  1. Local variable vs global variable
  2. closure scope

This StackOverflow link on Closure will help you understand better

Community
  • 1
  • 1
Samal
  • 31
  • 2