views:

227

answers:

2

There's a convoluted backstory involving how I came across this, but why is the self property not exactly equal to the window itself?

In Safari and Firefox and friends, the results are as I'd expect:

> window == window.self
  true
> window === window.self
  true

The same isn't true in Internet Explorer, though:

>> window == window.self
   true
>> window === window.self
   false

Can anybody account for the inconsistency? To exactly what is the self property of the window object pointing? It casts to something with equality, which is even more vexing.

+9  A: 

That's not all, window!==window.window!

I believe what we're probably seeing here is the difference between the ‘inner window’ and ‘outer window’ objects. Certainly other browsers have these (eg. Moz); they're typically used to present a different view of the window from inside and outside its own code.

The inner window holds your global variables and document-specific members. The outer window is accessible to [cross-frame-] scripting via window-references like frames[n], parent, opener, and apparently self. It is bound to the owner viewport (browser window/frame), so eg. when you navigate an iframe to a new document, the parent document still sees the same-identity window object in its iframe.

In a sensible Browser Object Model design there would be separate objects for this, but when JavaScript was originally thrown together by Netscape there was very little consideration for elegance, resulting in this and many other interfaces where there is too much overload (form with an element called submit, anyone?).

So for compatibility, the split window has to continue to appear to be a single object to scripts even though it isn't underneath. In IE, sometimes the mask slips: it seems like saying window gets you the inner window, and there's no hack to make it === against the outer window.

ETA: Actually come to think of it, there's even some (poor) justification for this. The ECMAScript spec, which is not written with multiple global contexts in mind, defines window, and the unbound version of this, as retrieving the global variable scope object, which would be the inner window.

The other properties, being part of the DOM/BOM, are not within the scope of the ECMA spec, so they can return something different (and must, for the sake of cross-frame scripting).

bobince
Wow, not sure I could have asked for a better answer.
Jim Puls
Where and in what ECMAScript spec do you see a definition for a `window` global object? Also, this whole inner and outer window stuff is BS. They are both the same `AbstractView`s as per the DOM (though obviously not in IE though). As expressed by JavaScript sharp variables, `window#1={window:#1#}`.
Eli Grey
@EliGray: ECMA262-3 s10.1.5, ECMA262-5 s15.1: “in the HTML document object model the `window` property of the global object is the global object itself”. You may think split windows are BS, but that is what most browsers do, and must do if they are to maintain the long-standing cross-frame-scripting behaviour(\*) that when you navigate a view to a new document, the reference you had to its `window` now points to the `window` of the new document view. (\*: IMO: misbehaviour, but it's no good trying to change that now.)
bobince
+2  A: 

Nice question. It does it with document and document.parentWindow too:

window == document; // true
window === document; // false

window == document.parentWindow; // true
window === document.parentWindow; // false

The big wtf for me though is:

window == document; // true
document == window; // false

You can swap out window with this in any of the above examples (and stay in the global context) with the same results. It makes the == operator even more suspect.

Why it behaves this way is so beyond me.

Crescent Fresh
Would have been better as a comment, as it doesn't answer the question.
musicfreak
Doesn't quite fit in a comment though, eh. It relates to the situation in that `document.parentWindow===window.self`. In my hypothesis (and who can say what's really happening given it's bloody IE), the explicit properties like `window.window`, `parent`, `self`, `opener`, `frame.contentWindow`, `document.parentWindow` get the outer window, whereas the implicit language-level constructs `window` and `this` give you the inner window.
bobince
[quite what's happening with the hilarious non-transitive window/document == comparison, though, I haven't the foggiest!]
bobince