Performance Implications of With Statements

javascript, with-statement

Solution

The problems with `with` statements are all rooted in the same problem: when using `with`, scoping becomes complicated.

Consider the following sample:

with (foo) {
    with (bar) {
        return x;
    }
}

This seems simple, but it actually can have all sorts of possible outcomes.

- If `foo` is defined and it has a property called `bar` and `bar` has a property called `x`, then `foo.bar.x` is returned.

- If `foo` is not defined but `bar` is and it has a property called `x`, `bar.x` is returned.

- If `foo` is defined but it has no property called `bar`, `bar` is retrieved using a `window` lookup.

The list goes on. So the behavior has all sorts of possibilities, and all of these are fragile and therefore possible bugs, but why is this a performance problem?

Well, consider this:

return foo.bar.x;

Without any `with` statements, this is easy for a JavaScript engine to optimize. Is a variable called `foo` in scope (declared using `var`)? If so, use that. If not, perform a `window` lookup. This can pretty much be determined statically.

When using `with`, every single variable lookup needs to be determined dynamically at runtime. If you're referring to a global variable inside of a `with` block, the engine still has to check if that property exists on the object being used with `with`. If `with` blocks are nested, it becomes even worse.

Using `with` makes behavior so complicated that in most cases, JavaScript optimizers will just give up because it throws a lot of compile-time guarantees out the window. When scope is determined dynamically, not lexically, it becomes very hard to reason about.

So yes, this is yet another reason why using `with` is a bad idea. Avoid it at all costs.

Problem

Okay, so, I have seen this mentioned now enough in the past forty-eight hours that I need to ask it as a question. In "JavaScript for Professional Web Developers" (2012) it says the same thing as it does on MDN: Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues. However, Zakas' book also states (without further substantive elaboration), that "[they should not be used] for performance reasons". This problem is apparently "bad enough" that in `Strict` mode, ECMAScript does not allow `with` statements. Is this really for performance reasons? Or, is it because people just couldn't stand them? If it is partly due in reality to performance, how and why do they negatively affect performance?

Original source