wallop
wallop

Reputation: 2581

is if block a separate closure in javascript

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
}

Upvotes: 1

Views: 582

Answers (2)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76413

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...

Upvotes: 8

iddqd
iddqd

Reputation: 1305

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

Upvotes: 2

Related Questions