1

From what i know, a function say A defined within another function say B has access to local variables of B as well.

function B() {
    var x = 10;
    function A() {
        console.log(x);    //will result in 10
        var y = 5;
    }
    console.log(y);    //ReferenceError: y is not defined
}

However in the below example y gets printed. I know there is no such thing as block scope in javascript for "if block" but shouldn a declaration atleast be invisible outside of "if" i mean shouldnt var y be limited to if block?

function B() {
    var x = 10;
    if(1) {
        console.log(x);    //will result in 10
        var y = 5;
    }
    console.log(y);    will result in 5
}
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
wallop
  • 2,510
  • 1
  • 22
  • 39
  • The answer is in the question: _"there is no such thing as block scope in JavaScript"_ – Cerbrus Aug 19 '14 at 09:10
  • 1
    is if block a separate closure in javascript? - no its not – Prabhu Murthy Aug 19 '14 at 09:11
  • @Cerbrus i was not sure of the linkage between block scope and closure concept. I was hoping the answer to this question would solve that one as well. I am pretty sure the "is if block a separate closure in javascript? " is a valid question and need not be down voted. I am also pretty sure "is if block a separate closure in javascript? " need not be interpreted as "is if block a separate block scope in javascript? " since i want to understand concepts in details – wallop Aug 19 '14 at 09:16
  • 1
    @Fishy: block-scope is what it is, see the first snippet in my answer: the loop has its own scope, outside of the loop, variables that were declared in it simply don't exist. A closure consists of elements that aren't accessible from the ouside, except through what the closure returns (a function, an object...). Cf the link in my answer – Elias Van Ootegem Aug 19 '14 at 09:19
  • yeah thanks, nice answer!!!Cant we consider the following concept also as closures apart from what you mentioned that returned objects/functions can access variables in outside scope. "any variable in a function is accessible down the child functions defined within that function but not the other way round" – wallop Aug 19 '14 at 09:39
  • @Fishy: I guess, that's what makes closures tick, however: I would refer to that as _scope scanning_. Any reference is resolved by first scanning the current scope, then the outer scope, all the way to the global scope. This also makes it clear why undefined variable assignments result in implied globals (when not in strict mode): JS tries to resolve the name first locally, and finally globally if it can't, the variable is created in the last scope JS searched for the variable... PS: if you like my answer, please consider accepting it – Elias Van Ootegem Aug 19 '14 at 09:57
  • yep you are right elias thanks : ). Pretty much explained a lot – wallop Aug 19 '14 at 09:58

2 Answers2

8

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...
Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
2

nope. as you said - if blocks does not have their own closures in JS - which means everything is part of the outer closure (in this case - y is a local variable in B's closure). so it will be completely visible in B's body

iddqd
  • 1,225
  • 2
  • 16
  • 34