Compare this code1:
somevar = 5;
delete window.somevar;
alert(typeof somevar) //=> undefined, so deleted
to this cod
What you're seeing is an aspect of the fact that the global object (window
, on browsers) is a conflation of two different things which are distinct everywhere except the global execution context.
In the first block, someVar
is a normal property of the window
object. Properties can be removed via delete
.
In the second block, someVar
is a property of the binding object of the variable context of the global execution context — which is also window
. You cannot delete properties the binding object receives in its role as the binding object (even though you can delete properties it receives in other ways). That is, you cannot delete variables declared with var
(and a few other things that are added the same way).
(Sorry, not my terminology; it comes from the spec, which features some very fun language indeed.)
It's only the global execution context where we have this conflation of concepts. The variable binding object for other execution contexts (function calls, for instance) is still a very real thing (and crucial to proper functioning of closures), but there's no programmatic way to directly access it. In the global execution context, though, it's the global object, which of course we can access.
It helps to understand this if we look at functions first, and then look at the global execution context. when you call a function, these things happen:
this
to point to the object designated by the call (the value of this
is usually implicitly set, but there are ways to set it explicitly).arguments
property to the binding object, referring to the pseudo-array of arguments to the function.var
statements (anywhere in the function body) as properties of the binding object, initially with the value undefined
....and then step-by-step execution of the code in the body of the function begins. Any var
statements with initializers (e.g., var a = 5;
rather than just var a;
are treated as assignment statements (a = 5;
) when the execution point reaches them.
Throughout the above, whenever a property is added "to the binding object", it's added with a flag indicating that it cannot be deleted. This is why var
s (and the names of declared functions, etc.) can't be deleted.
Any unqualified reference is looked up via the scope chain. So when you refer to a
in your code, the first place the interpreter looks is the binding object at the top of the scope chain. If it has a property called a
, that's what gets used; if not, we look at the next link down the scope chain and use that property if we find it; and so on until we run out of links on the scope chain. The global object is the bottommost link of that chain (which is why global variables work).
So what's different about the global context? Well, very little, actually. Here's the sequence (roughly):
this
to point to the binding object; that makes it the global object.window
is added to the object, referring to itself)....and then we basically pick up with step 8 in the function stuff:
var
statements (anywhere in the global scope) as properties of the binding/global object, initially with the value undefined
....and start step-by-step execution of the code (again with var
initializers becoming assignments).