Another improvement related to 'var'.
Saturday, November 27, 2010 at 11:48AM Wrote yesterday about the new warning if a local variable is used before it is declared with 'var'. A related issue is var-declarations inside nested blocks. Say:
if (2+2=5) {
switch (true) {
case false:
var location;
}
}
location = "something"
Here the var-statement does occur before the first reference to the variable, but the var-statement is nested inside if- and switch-blocks, which makes it easy to miss, and it is counter-intuitive that a deeply nested statement will change the meaning of a variable in an outer block. Furthermore, the statement cannot possibly ever be executed as the code looks now - but the var still have effect.
All this is highly counter-intuitive, and makes it unnecessary tricky to read code. Therefore Mascara provides a simple fix.
The new rule is: A local variable can only be accessed in the same block, or in nested blocks inside the block where the variable is declared with var.
E.g. this is legal:
var location = "hello";
location = "goodbuy";
And this is legal:
var location = "hello";
if (something) {
location = "goodbuy";
}
And this is legal:
if (something) {
var location = "hello";
location = "goodbuy";
}
But this is not legal, because the variable is used outside the block with the var-statement:
if (something) {
var location = "hello";
}
location = "goodbuy"; //WARNING!
The last example will generate a ´Name not found: 'location' in function scope´-warning.
This is a small fix, but it is the accumulation of small things like these which makes the difference between long nights of bug-tracing, enjoyable development of new features.
Clarification: this does not change the run-time semantics of the var statement, it is just a compile-time verification which avoids some confusing and potentially buggy patterns. It is therefore not equivalent to the proposed 'let'-scopes which does change the semantics, e.g. by allowing you to 'shadow' variables declared in an outer scope.
Olav | Comments Off |
Reader Comments (4)
Are you saying that your last example is illegal ECMAScript code (or illegal in strict mode)? I've done
if (!something) {var something = ...;}quite a few times and I thought that was perfectly legal.Basically you've changed `var` to be `let`, at the cost of (probably?) an additional anonymous function for any block scope (including the additional cost of calling the function and having an extra context in your scope chain) and screwing up the most basic knowledge for any decent js developer. Sounds like a good job.
@Eli: No, it is valid ECMAScript 5 code, even in strict mode. But the Mascara compiler will give a warning.
@Peter: No, the compiler does not create any additional anonymous functions. It is simply a compile-time warning which will prevent some bugs.
'Let'-scopes could be implemented as you suggest basically by creating an anonymous function for the block. But it is somewhat more tricky than just creating an anonymous function, since 'return', 'break' and 'continue' could occur inside the let-scope.