JavaScript doesn't have block scope at all (yet, see below). All variables are declared throughout the function in which they appear (or throughout the global scope, if they're at global scope).
Assuming the code you've quoted is the only code in its scope, it's exactly the same as this:
var i;
var Proof;
var Callback;
for(i=0;i<3;i++){
Proof = true
if (i == 0){
Proof = false
//CallBack = function(){alert(Proof);}; // true????
CallBack = function(){alert(i);};
}
}
// Whatever happened to local scope? shouldn't CallBack be undefined now?
CallBack()// alert(3), should be 0?
More (on my blog): Poor, misunderstood var
CallBack()// alert(3), should be 0?
No, 3
is correct, because that's the value of i
as of when CallBack
is called. CallBack
is a closure over the context in which it was created. It has an enduring reference to the context (including the i
variable), not a copy of what existed when it was created.
If you wanted to get 0
instead, you'd have to have CallBack
close over something other than i
, something that won't change. The typical way to do that is to use a builder function you pass a value into:
function buildCallBack(index) {
return function() { alert(index); };
}
Then:
CallBack = buildCallBack(i);
The value of i
is passed into buildCallBack
as the argument index
. buildCallBack
creates a function closing over the context of that call to buildCallBack
and using that index
argument. Since that argument's value is never changed, the callback alerts 0
(in this case) rather than 3
.
More (on my blog): Closures are not complicated
The reason I said "yet" above is that the next version of the spec (ES6) will introduce new block-scope semantics for the new let
and const
keywords and block function declarations. var
will be unchanged, but if you use let
to declare a variable instead, it has block scope rather than function/global scope.