One reason for this is due to the fact that JavaScript operates under function scope, not block scope. This means that any variable you declare within a loop will be within the function's scope, allowing every closure to access the same variable.
In order to create a new scope, it is necessary to invoke a function, which is exactly what
(function(i){/* Some code using i */}(i))
accomplishes.
It is important to note that in your example, a crucial component is missing: The immediate function must return another function that serves as the click
handler:
someArray[i].onclick = (function(i){
return function() {
/* Some code using i */
}
}(i));
The immediate function is essentially just a way to combine function definition and function call. It can also be replaced by 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);
}