andrew.hedges.name / blog

When is a global variable not a variable?

April 7, 2010, 1:37 pm · 5 comments · Filed under: JavaScript

I’ve started reading Dmitry Soshnikov’s excellent series, ECMA-262-3 in detail. I’m only on chapter 2 and I’ve already learned a thing or two. I highly recommend it for anyone who wants to know JavaScript at a deep level.

Spoiler alert: I’ll spare you reading the whole post if you’re in a hurry. When is a global variable not a variable? When it is a property of the global object.

There, satisfied? Buh-bye. Want to know why? Read on…

Chapter 2 of Dmitry’s series on JavaScript covers the variable object. One of the interesting details about this concerns how variables are created. Specifically, variables (that is, mutable values of the variable object type) are only created using the var statement.

“Aha, not so!” I can hear you thinking. (Or, maybe that was you sneezing. In that case, gesundheit.) “If you set a variable without using the var statement, it just becomes a global variable!”

OK, there’s a lot less suspense involved in this because I gave away the answer at the top, but the truth is that, no, by omitting the var statement, you don’t create a global variable. You create a property on the global object. Esoteric, but true!

Time for some examples

The following examples match very closely those in Dmitry’s article. The main difference is that I wrapped the first alert in each example in a try/catch block so you will see the error thrown, if any.

I recommend studying each of them and trying to predict the result of each before clicking the “Run it” link. (That link, by the way, will load a file into a tiny iframe, executing the code inline in that page.)

try {
   alert(a);
}
catch (e) {
   alert(e);
}

var a = 10;

alert(a);

Run it

try {
   alert(b);
}
catch (e) {
   alert(e);
}

b = 20;

alert(b);

Run it

Did the scripts do what you expected? Did you notice the difference?

In the first example, we first get an alert of “undefined” (it doesn’t actually hit the catch block). This is because, even though we haven’t yet declared it (and due to a thing called variable hoisting), a variable object with the name a has been created at the time the script was interpreted. So, when the script is actually executed, the variable already exists, but hasn’t been assigned a value yet.

In the second example, executing the first alert throws a reference error. The variable has not been hoisted in the interpretation phase, so it is not available in the execution phase when we first try to alert it.

In a practical sense, the difference between the two is not likely to have much effect. Both the variable a and the global property b can be accessed later, modified, etc.

The biggest difference between the two is that variables (that is, ones declared with the var statement) can’t be deleted using the delete statement. Properties can.

Was this helpful? Let me know in the comments if you’d like me to post more articles like this one.


Update (9 April 2010): As Dmitry, himself, points out in the comments, there is one other case to consider. The eval statement constructs variables without the {DontDelete} attribute, even using the var statement. Consider the following:

var x = 10;

alert(delete x);

try {
   alert(x);
}
catch (e) {
   alert(e);
}

Run it

eval('var y = 20');

alert(delete y);

try {
   alert(y);
}
catch (e) {
   alert(e);
}

Run it

You should have seen alerts of “false” and “10” in the first case (ie. the variable was not deleted) and “true” and a reference error in the second (ie. the variable was deleted).


Short URL to this article:

5 comments


Very interesting! A subtle distinction, but worth noting. JS might be the apex of widely used, poorly studied.

Thanks for this writeup. You wrote shortly and the main general point. I am glad to see that becomes more and more programmers interested in deep JS.

A short addition:

There is one context in which {DontDelete} for variables has no effect; it is context of eval code. Which cause misconceptions sometimes when some test the code e.g. in Firebug which also uses eval to execute the code (I saw such mistakes in some books on JavaScript where Firebug is mentioned for testing).

var x = 10;
alert(delete x); // false, as has {DontDelete}
alert(x); // 10

eval("var y = 20");
alert(delete y); // true
alert(y); // ReferenceError

Dmitry.

Dmitry,

Thanks for responding to my post! I ran your examples through both Safari’s and Firefox’s consoles and got a different result. I was able to delete both variables. Is this a bug in their implementations or, perhaps, something intentional on their part?

> var x = 10;
undefined
> delete x;
true
> x
ReferenceError: Can't find variable: x

> eval("var y = 20");
undefined
> delete y;
true
> y
ReferenceError: Can't find variable: y

Dmitry responded on Twitter:

That’s because Safari’s console also uses eval to execute the code. And in eval context we have no {DontDelete} for vars. Try it with simple test.html file, var x = 10; delete x; alert(x); - should be still 10 for current Safari. But not with eval.

Of course! He even mentions this in his article, but it must have slipped my mind. I’ve posted an update with 2 new files that illustrate Dmitry’s point.

thx, it helped me greatly but i have 1 question:
is global variable a property of global object (in browser case - window object)?

var a = "i'm global variable";
b = "i'm property of global object";

document.writeln(window.a); //"i'm global variable"
document.writeln(window.b); //"i'm property of global object"

it seams that it is, but special (undeletable) one:

document.writeln(delete window.a); //false
document.writeln(delete window.b); //true
Comments close automatically after 15 days.
Still have something to say? Drop me a line!