JavaScript isn't truly block scoped. An if
or for
loop does not have its own scope. All variable declarations in any given scope (that is: global scope, or a function) are hoisted, and this visible anywhere inside that scope.
ECMAScript6 (Harmony) will, in all likelihood, introduce block-scope to JS, through the use of the new let
keyword see the wiki:
for (let i=0;i<12;++i)
{
console.log(i);//logs i
}
console.log(i);//reference error
There also seems to be some confusion as far as terminology is concerned here: a closure is not the same as a scope.
The snippet above is an example of block-scoped code. The variable i
is created at the start of the loop, and simply ceases to exist once the loop finishes. It is GC'ed (Garbage Collected). i
is no more, bereft of life it rests in peace. Closures are something different entirely: they rely on variables that are not GC'ed, but can't be accessed from outside code. They can only be accessed through the return value of the closure:
var someClosure = (function()
{//this function creates a scope
var x = 123;
return {
getX: function()
{
return x;
},
setX: function(val)
{
return x = val;
}
};
}());
console.log(x);//reference error
console.log(someClosure.getX());//returns 123, so "x" still exists
That being said:
You can mimic a block-scoped loop through the use of a closure, though. Functions are scoped, and a closure is a function or object that is returned by a function. That means that the return value of a function has access to the entire function's scope. See this answer for details.
Apply what is explained there, and work out why this loop is "pseudo-scoped":
var foo = [1,2,3,4,5,6],
largerThan3 = (function(arr)
{
var resultArr = [];
for (var i=0;i<arr.length;++i)
{
if (arr[i] > 3)
resultArr.push(arr[i]);
}
return resultArr;
}(foo));
console.log(i);//reference error...