In javascript, the only way to create a new variable scope is in a function.
Whether or not the new scope is needed will depend entirely upon the circumstance. As such, the generic examples you presented don't allow a definitive answer.
To give something more concrete, take we can your test 2, and apply this very common scenario where the someoperations
is an asynchronous call like a setTimeout
:
for( var i=1; i<4; i++ ) setTimeout( function() { alert( i ); }, 1000 * i);
The trouble is that each function created in the loop (and passed to the setTimeout
) references the same i
variable, and because it is a setTimeout
, which is non-blocking, the loop finishes in its entirety before any of the functions created in the loop are ever invoked.
The result is that each function will alert 4
since that was where the value of i
was left after the loop.
Example: http://jsfiddle.net/Ng3rr/
On the other hand, if you invoke a function inside the loop that sets up your setTimeout
, passing the value of i
to that function, then the variable referenced by each function sent to setTimeout
will be the local inner_i
, which referenced the value that was passed into that outer invocation.
(I called it inner_i
to differentiate between the two, but you could name the inner variable i
as well. Doing so is called variable shadowing.)
for( var i=1; i<4; i++ )(function( inner_i ){
setTimeout( function() { alert( inner_i ); }, 500 * inner_i);
})( i );
Now each alert displays the value that was received during each iteration.
So as you can see, it depends entirely on the situation.
Example: http://jsfiddle.net/Ng3rr/1/
To add some contrast to the examples above, if we didn't run any asynchronous code in the loop, the outer function would be unnecessary.
This:
for( var i=1; i<4; i++ ) alert( i );
Example: http://jsfiddle.net/Ng3rr/2/
...and this:
for( var i=1; i<4; i++ )(function( inner_i ){
alert( inner_i );
})( i );
Example: http://jsfiddle.net/Ng3rr/3/
...will have identical behavior, making the outer function unnecessary.
So invoking an outer function creates a new variable scope. In that new scope, the variables will be retained by any additional nested functions created in that scope.
Also, while variables created in that scope are accessible in the functions nested in that scope, they're unavailable outside that scope. This keeps you from polluting the surrounding scope with additional variable names.