A loop that goes over all the divs in a given container incorrectly assigns classes to the onmouseout event

for (var i=0; i<divs.length; i++){ var cssClass = 'box n'+(i+1); //создаем класс 'box n1' divs[i].className = cssClass; divs[i].onmouseover = function(){ this.className= cssClass+' hover' } divs[i].onmouseout = function(){ this.className= cssClass } //console.log(cssClass); Показывает что в каждой итерации класс правильный } 

The mistake is that when an event occurs, an element is not hung on its own class, but on the class of the last element, in this case 'box n42', instead of its own. Why does this happen, because the console shows that in each iteration, when the event is hung the class is correct?

    2 answers 2

    The problem is due to the fact that when using variables from parent functions (in this case, cssClass ) in closures, when directly calling a closure, the value of the variable will be as it was after the last assignment. To solve this, you can, for example, wrap the code in the loop iteration into an anonymous function to create your scope:

     for (var i=0; i<divs.length; i++){ (function(){ var cssClass = 'box n'+(i+1); divs[i].className = cssClass; divs[i].onmouseover = function(){ this.className= cssClass+' hover' } divs[i].onmouseout = function(){ this.className= cssClass; } })(); } 

    Here is a good article on closures.

      The class name cannot contain space characters - otherwise you will have 2 classes.
      I did not peer into the code - my knowledge of pure js is insignificant ...
      Here is an analogue of your code, but on jQuery:

       $(document).ready(function(){ var iterator = 1; $("#some_divs_selector").each(function(){ var myClass = "some_class_" + iterator++; $(this).addClass(myClass); }); });