Please explain the closure or link the loop counter to the function area

I have seen programmers assign event listeners within loops using a counter. I believe this is the syntax:

for(var i=0; i < someArray.length; i++){ someArray[i].onclick = (function(i){/* Some code using i */})(i); } 

Can anyone explain the logic of this and this weird syntax, I have never seen this:

 (function(i))(i); 

Thanks so much for your time and patience.

+7
source share
2 answers

This is because JavaScript has only a function area , not a block area. Therefore, every variable you declare in a loop is in the function area, and every closure you create has access to the same variable.

So the only way to create a new scope is to call a function, and this is what

 (function(i){/* Some code using i */}(i)) 

does.

Note that your example skips the important part: the immediate function should return another function that will be the click handler:

 someArray[i].onclick = (function(i){ return function() { /* Some code using i */ } }(i)); 

The immediate function is nothing special. It is somehow embedding a function definition and calling a function. You can replace it with a regular function call:

 function getClickHandler(i) { return function() { /* Some code using i */ } } for(var i=0; i < someArray.length; i++){ someArray[i].onclick = getClickHandler(i); } 
+5
source

The syntax (function(i))(i) creates an anonymous function and immediately executes it.

Usually you will create a new function every time through a loop that has its own copy of the variable, and not every event handler that uses the same variable.

So for example:

 for(int i = 0; i < 10; i++) buttons[i].click = function() { doFoo(i); }; 

Often catches people, because no matter what button you press, doFoo(10) called.

While:

 for(int i = 0; i < 10; i++) buttons[i].click = (function(i){ return function() { doFoo(i); };)(i); 

Creates a new instance of the internal function (with its i value) for each iteration and works as expected.

+7
source

All Articles