Javascript variable scope in addEventListener anonymous function

When clicking on each div, it should warn β€œ1” if the β€œ1” button is pressed or β€œ5” if the β€œ2” button is pressed. I tried to make this code as simple as possible because it is needed in a much larger application.

<html> <head> <style type="text/css"> #div1 { background-color: #00ff00; margin: 10px; padding: 10px; } #div2 { background-color: #0000ff; margin: 10px; padding: 10px; } </style> <script type="text/javascript"> function init() { var total = 1; var div1 = document.getElementById('div1'), div2 = document.getElementById('div2'); var helper = function(event, id) { if (event.stopPropagation) event.stopPropagation(); if (event.preventDefault) event.preventDefault(); alert('id='+id); } div1.addEventListener('click', function(event) { helper(event, total); }, false); total += 4; div2.addEventListener('click', function(event) { helper(event, total); }, false); } </script> </head> <body onload="init();"> <div id="div1">1</div> <div id="div2">2</div> </body> </html> 

Thanks for your help!: -)

+4
source share
2 answers

The problem is that event listeners and "total" both exist in the same scope (init ())

Event functions will always refer to the final value within the init () scope, even if it changes after the event functions are declared.

To get around this, the functions of the events must have a "common" in their field, which will not change. You can add another level of visibility using an anonymous function.

For instance:

 (function (total) { div1.addEventListener('click', function(event) { helper(event, total); }, false); }(total)); total += 4; (function (total) { div2.addEventListener('click', function(event) { helper(event, total); }, false); }(total)); 

Anonymous functions are passed init () current 'total' as a parameter. This sets another β€œcommon” in the scope of the anonymous function, so it doesn't matter if init () changes or not, because the event function will FIRST refer to the scope of the anonymous function.

Edit:

In addition, you must place a semicolon after the closing bracket of the helper function, otherwise the script will complain that the "event" is undefined.

 var helper = function(event, id) { if (event.stopPropagation) event.stopPropagation(); if (event.preventDefault) event.preventDefault(); alert('id='+id); }; 
+8
source

This is pretty much the same, but I think it would be better:

 div1.addEventListener('click', function(t){ return function(event) { helper(event, t); }}(total), false); 

instead:

 (function (total) { div2.addEventListener('click', function(event) { helper(event, total); }, false); }(total)); 
+2
source

All Articles