Google Groups

Re: Why "window.alert()" over "alert()"?


Lasse Reichstein Nielsen Aug 24, 2008 4:55 AM
Posted in group: comp.lang.javascript
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Gregor Kofler wrote:
>> In case of "alert()" JS will search through the scope chain, until an
>> alert-named function is found. It will finally end up at the global
>              ^^^^^^^^ property                            ^^^^^^^^^^
>> object, in browsers the window object.
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> This assertion is based on wishful thinking, still not backed up by any
> public standard or exhaustive research.  You would be well-advised not to
> advocate it.

It does seem that the global object's "window" property holds a
reference to the global object itself in all current browsers, to the
point where a new browser would be causing itself problems by not
doing the same.
No standard, true, except de-facto standard.

> In fact, there is evidence to the contrary: MSHTML's creating "read-only"
> properties of a host object in the scope chain to refer to element objects
> representing elements with ID or name, also being available through the
> `window' reference.  

They are equally available through the global object. They are not
ReadOnly as properties of the global/window object, though, only when
resolved through the scope chain.

> But the Global Object is specified as a native object,
> it has to implement the [[Put]] method exactly as it was specified; so that
> cannot be the object referred to by `window', which exhibits said behavior
> instead.

That, or IE doesn't follow the specification and implements [[Put]]
differently on the global object.

It does appear that MSHTML has an a step in the variable resolution
procedure that acts as if there is an object above the global object,
that holds those element-id properties. It also appears that reading
the properties directly off the global object will also give the
element with that id. This gives two ways to give the same result,
and the two are not equivalent.

Example:

 <div id="foo">foo</div>
 <script type="text/javascript">
   alert([foo, typeof foo, window.foo, typeof window.foo]);
   // alerts "[object],object,[object],object"

   alert("foo" in window);
   // alerts true

   try { foo = 42; } catch(e) { alert(e.message); }
   // alerts "Object doesn't support this property or method"

   window.foo = "window.foo";
   alert([foo, typeof foo, window.foo, typeof window.foo]);
   // alerts "[object],object,window.foo,string"

 </script>
 <script type="text/javascript">
   var foo = 37;
   alert([foo, typeof foo, window.foo, typeof window.foo]);
   // alerts "37,number,37,number"
   // a function declaration also changes both.
 </script>

Using the global object instead of "window" gives exactly the same
result (they are the same object, as reported by "==").

I.e., the scope-lookup appears to match page id's just before it
tests the global object. There may or may not be an object holding
the properties (I'm expecting that there isn't, and that they are
instead resolved by extending the lookup algorithm directly).

The property is not writable, but it does shadow the same property
in the global object.

It appears that the id-elements are *also* properties of the
global/window object, but these properties are not ReadOnly
and can be overwritten. After this, "foo" and "window.foo"
resolves to different values.

And further, if a variable or function with the same name is declared
in the global scope, "foo" no longer resolves to the element with that
id.


Even more interesting, the behavior depends on whether one reads the
property of the global objecct as an element before assigning it
another value:
 
 <script type="text/javascript">
   // window.bar = 42;        // [1]
 </script>
 <div id="bar">bar</div>
 <script type="text/javascript">
   //alert([bar, typeof bar, window.bar, typeof window.bar]); // [2]
   window.bar = "window.bar";
   alert([bar, typeof bar, window.bar, typeof window.bar]);
   // alerts "window.bar,string,window.bar,string"
 </script>

In the above, if [2] is uncommented, the final alert changes
to "[object],object,window.bar,string". I.e., the action of
*reading* "bar" as the element with that id causes later
references to give the same result.

If [1] is also uncommented, the final alert changes back again.
I.e., if a property of the name is already on the global object
when the element is parsed and added to the DOM, then its name is
not resolved specially and it is not set on the global object.


Ok, this was a diversion. The point is: There global object and
the value of the "window" property of the global object is the
same object in MSHTML, just as in the other current browsers.

My bet is that you can expect that to stay true.

...
> That is not the reason why.  Because if someone declared `window' in the
> scope chain before the Global Object (so as this would not refer to the
> `window' property of the Global Object anymore), then the issue remained.
> It is instead that it is unlikely that someone would do that.
>
> To be absolutely sure, one would have to feature-test and use
> global.window.alert(), with `global' being a globally defined reference to
> the Global Object (var global = this), instead.

That's not being "absolutely sure". The "global" property could
equally well have been overwritten or shadowed, and it's probably even
more likely than someone shadowing "window" or "alert", since those
are well known global properties.

To be absolutely sure, you should create a reference to the global
object at the point where it is needed, so you don't rely on a binding
that could be overwritten or shadowed.

e.g.
 var global = (function(){return this;})();
 global.alert(global == global.window);

(which, by the way, alerts "true" in all the browsers I have available,
including in MSHTML :).

/L
--
Lasse Reichstein Nielsen
 DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
  'Faith without judgement merely degrades the spirit divine.'