Variable Renaming With and Eval Statements- Not!

Modified on 2009/12/14 23:01 by Stephen Walther — Categorized as: Uncategorized

Renaming of local variables and functions really only works if the code is completely known at parsing time. Unfortunately that isn’t always the case with JavaScript. There are two statements in particular that determine the scope chain at runtime: with and eval.

The with statement takes an expression that evaluates at runtime to an object that is placed at the head of the scope chain. For example:

var foo = 10;
with(window)
{
    alert(foo);
}

With this code, we have no idea at parse time whether “foo” is referring to the local variable or to a property on the window object.

The eval statement is even more destructive to the variable-renaming algorithm. It takes an expression that evaluates to a string that is then parsed and executed as more JavaScript code. There is no way to programmatically determine at parse time if the string will declare more variables or functions, reference existing variables or functions, or whatever.

The eval statement marks its containing scope as “unknown.” Scopes that are unknown at parse time may have significant errors introduced if they depend on existing variables and functions. The –EVALS switch modifies this behavior to reduce the minification of the algorithm, but remove the risk of the eval statement. If –EVALS:MAKESAFE is specified, no “unknown” scopes will participate in the variable renaming process. This ensures that the code that is run in an eval statement will continue to work in minified code, just as it would in the original sources. If the developer knows that the eval statement will only need variables or functions defined in the containing scope and not in any of the parents, the –EVALS:IMMEDIATE switch can be used. The containing scope will not participate in the local-renaming process, but parent scopes will continue to do so.

In the with statement example above, if we were to change the variable “foo” to “a” and the window object doesn’t contain a “foo” property, we’ve broken the link to the local variable. And if we also change the parameter to the alert function, we could be breaking the link to a foo property on the window object. Every variable and function referenced within a with-scope must remain the same name because we just don’t know.

If you must use eval and with statements, try to isolate them into small scopes under the global level that are tightly coded without long variable or function names. In general, these statements are frowned upon by most JavaScript developers anyway, and the use of them will throw a level 4 warning in AjaxMin.