Behavior of local variables in JavaScripts with()-statement

Posted by thr on Stack Overflow See other posts from Stack Overflow or by thr
Published on 2010-04-10T10:23:50Z Indexed on 2010/04/10 10:33 UTC
Read the original article Hit count: 283

Filed under:
|

I noticed some weird (and to my knowledge undefined behavior, by the ECMA 3.0 Spec at least), take the following snippet:

var foo = { bar: "1", baz: "2" };
alert(bar);
with(foo) {
    alert(bar);
    alert(bar);
}
alert(bar);

It crashes in both Firefox and Chrome, because "bar" doesn't exist in the first alert(); statement, this is as expected. But if you add a declaration of bar inside the with()-statement, so it looks like this:

var foo = { bar: "1", baz: "2" };
alert(bar);
with(foo) {
    alert(bar);
    var bar = "g2";
    alert(bar);
}
alert(bar);

It will produce the following:

undefined, 1, g2, undefined

It seems as if you create a variable inside a with()-statement most browsers (tested on Chrome or Firefox) will make that variable exist outside that scope also, it's just set to undefined. Now from my perspective bar should only exist inside the with()-statement, and if you make the example even weirder:

var foo = { bar: "1", baz: "2" };
var zoo;
alert(bar);
with(foo) {
    alert(bar);
    var bar = "g2";
    zoo = function() {
        return bar;
    }
    alert(bar);
}
alert(bar);
alert(zoo());

It will produce this:

undefined, 1, g2, undefined, g2

So the bar inside the with()-statement does not exist outside of it, yet the runtime somehow "automagically" creates a variable named bar that is undefined in its top level scope (global or function) but this variable does not refer to the same one as inside the with()-statement, and that variable will only exist if a with()-statement has a variable named bar that is defined inside it.

Very weird, and inconsistent. Anyone have an explanation for this behavior? There is nothing in the ECMA Spec about this.

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about jQuery