function foo0() {
    var bar = 2;
    alert("outer block: "+bar);
    if (true) {
       var bar = 3;
       alert("inner block: "+bar);
    }
    alert("outer block: "+bar);
}
Because JavaScript scoping is at the function and object levels, block scoping can be simulated with anonymous functions and anonymous objects.
Function-based Block Scoping
Anonymous functions can simulate block scoping by defining a closure and calling it:
function foo1a() {
    var bar = 2;
    alert("outer block: "+bar);
    if (true) (function() {
       var bar = 3;
       alert("inner block: "+bar);
    })();
    alert("outer block: "+bar);
}
The parentheses around the closure are necessary to avoid a syntax error when calling the closure immediately. Formal arguments are also considered to be at the function scope, and they can be used to bind the block scoped variables:
function foo1b() {
    var bar = 2;
    alert("outer block: "+bar);
    if (true) (function(bar) {
       alert("inner block: "+bar);
    })(3);
    alert("outer block: "+bar);
}
Another implementation of block scoping with closures uses the new operator that automatically calls its function:
function foo1c() {
    var bar = 2;
    alert("outer block: "+bar);
    if (true) new function() {
       var bar = 3;
       alert("inner block: "+bar);
    };
    alert("outer block: "+bar);
}
The syntax of the new operator is a bit tidier.
Object-Based Block Scoping
Just as an anonymous function can implement block scoping, so too can an anonymous object, using the with statement:
function foo2a() {
    var bar = 2;
    alert("outer block: "+bar);
    if (true) with({ bar:3 }) {
       alert("inner block: "+bar);
    }
    alert("outer block: "+bar);
}
Of all of these examples, the with statement has the tidiest syntax -- but only those members in the anonymous object are block scoped. Thus, variables of both function and block scope can be mixed within the same block:
function foo2b() {
    var bar = 2;
    var baz = 1;
    alert("outer block: "+baz);
    if (true) with({ bar:3 }) {
       var baz = 4;
       alert("inner block: "+baz);
    }
    alert("outer block: "+baz);
}
In this example, the second outer block alert for baz is 4, because baz still has function scope. It remains to be seen whether this ability to mix scoping is a bug (more confusing) or a feature (more flexible) for the with statement version.
 
 

No comments:
Post a Comment