Question : is there any difference between declaring a variable
var a=0;//1
and this way
a=0;//2
or
window.a=0;//3
in global scope?
Soloution: Yes, there are two differences, though in practical terms they're not usually big ones.
three statements explained
var a=0;
...creates a variable on the variable object for the global execution context, which is the global object, which on browsers is aliased as
window
(and is a DOM window object rather than just a generic object as it would be on non-browser implementations). The symbol window
is, itself, actually a property of the global (window) object that it uses to point to itself.
The upshot of all that is: It creates a property on
window
that you cannot delete. It's also defined before the first line of code runs (see "When var
happens" below).
Note that on IE8 and earlier, the property created on
window
is not enumerable (doesn't show up in for..in
statements). In IE9, Chrome, Firefox, and Opera, it's enumerable.a=0;
...creates a property on the
window
object implicitly. As it's a normal property, you can delete it. I'd recommend not doing this, it can be unclear to anyone reading your code later.
And interestingly, again on IE8 and earlier, the property created not enumerable (doesn't show up in
for..in
statements). That's odd, particularly given the below.window.a=0;
...creates a property on the
window
object explicitly. As it's a normal property, you can delete it.
This property is enumerable, on IE8 and earlier, and on every other browser I've tried.
A fourth way
There's yet another way to do this, btw:
this.a=0;
...because in the global execution context,
this
references the global object. So this.a=0;
is identical to window.a=0;
(except it may be a teensy, teensy bit faster because this
doesn't have to be looked up; probably impossible to measure in any real world scenario).
Since this is the same as
window.a=0;
, it's no surprise that this creates an enumerable property (even on IE8 and below).Deleting properties
What do I mean by "deleting" it? Exactly that: Removing the property (entirely) via the
delete
keyword:window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
delete
completely removes a property from an object. You can't do that with properties added to window
indirectly via var
, the delete
is either silently ignored or throws an exception (depending on the JavaScript implementation and whether you're in strict mode).
Warning: Internet Explorer won't let you delete properties of the
window
object, even when you should be allowed to. Worse, it throws an exception when you try (try this experiment in IE and in other browsers). So when deleting from the window
object, you have to be defensive:try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
That tries to delete the property, and if an exception is thrown it does the next best thing and sets the property to
undefined
.
This only applies to the
window
object, and only (as far as I know) to IE. Other browsers are fine with deleting window
properties, subject to the rules above.
When var
happens
There's another difference between the
var
version and the others. It relates to when the symbol is created. The symbols defined via the var
statement are created before any step-by-step code in the execution context is run, and so the property exists well before the var
statement.
This can be confusing, so let's take a look:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
As you can see, the symbol
foo
is defined before the first line, but the symbol bar
isn't. Where the var foo = "f";
statement is, there are really two things: defining the symbol, which happens before the first line of code is run; and doing an assignment to that symbol, which happens where the line is in the step-by-step flow. (See Poor misunderstood var
)
Off-topic: Avoid cluttering window
The
window
object gets very, very cluttered with properties. Whenever possible, strongly recommend not adding to the mess. Instead, wrap up your symbols in a little package and export at most one symbol to the window
object. (I frequently don't export any symbols to the window
object.) You can use a function to contain all of your code in order to contain your symbols, and that function can be anonymous if you like:(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
In that example, we define a function and have it executed right away (the
()
at the end).
A function used in this way is frequently called a scoping function. Functions defined within the scoping function can access variables defined in the scoping function because they're closures over that data ..
Comments
Post a Comment