Natarajan Shanker
Natarajan Shanker

Reputation: 443

Whats going on with this JavaScript snippet?

From http://dmitry.baranovskiy.com/post/91403200

if (!("a" in window)) {
    var a = 1;
}
alert(a);

Here are the results I got:

What's going on??! I expected undefined, since the "if" should return a false (since "a" in window should be false, and !false should be true, therefore the variable a never gets a value). What am I missing?

EDIT: Ok, I realized var statements are executed first, and "a" in window just returns whether such a variable exists or not. But then why are Firebug and jsfiddle giving different answers?

Upvotes: 0

Views: 82

Answers (1)

jfriend00
jfriend00

Reputation: 707158

This code gets seen by the javascript interpreter as this:

var a;
if (!("a" in window)) {
    a = 1;
}
alert(a);

You have four permutations for this code based on whether a already exists in the global scope and whether the code is run in the global scope or in a local scope.

If the code is run in a local function scope, then it essentially looks like this:

function whatever() {
    var a;
    if (!("a" in window)) {
        a = 1;
    }
    alert(a);
}

So, here are the permutations:

global a exists already      scope code runs in       value of alert(a)
-----------------------------------------------------------------------
yes, has value of 2          global                   2
yes exists, value undefined  global                   undefined
no                           global                   1
yes, has value of 2          local                    undefined
yes exists, value undefined  local                    undefined
no                           local                    1

So, the variation in answers you are getting is because the scope this code is running in is different in each case.

In a jsFiddle, you have to be careful with the settings in the upper left corner. If set to onload, then the jsFiddle runs in a local function scope (an onload handler function).

What's going on here is that if this code is running the global scope, then ("a" in window) will always be true because the var a part of the code is hoisted above the executing code thus var a in global scope has always been executed so there is always ("a" in window). Thus a = 1 is never executed when run in the global scope and the alert(a) simply outputs whatever the value of global a is. If it previously had a defined value that's what you will see. If it didn't previously have a defined value, then it will just alert undefined because (thought it exists), it hasn't been assigned a value.

If this code is run in the local scope, then the alert(a) will always see the locally defined a in the alert(a). So, you will see 1 as the value if there is no global a because then a = 1 will execute on the local a. Or, if there is a global a, then the a = 1 will never execute, thus the locally defined a will always be undefined and that's what the alert will show.

Upvotes: 2

Related Questions