Understanding Web API DOM interfaces - javascript

I'm trying to learn more about Web APIs. Reading about them I see that among the wide variety of web API's there's the DocumentObjectModel API. Reading about the DOM specifications, I find a list of a lot of DOM interfaces. This makes me feel a little upset. In my ignorance, I think that an API should contain only one interface (only one set of functions and properties), here I find a list of interfaces...and that's the first thing that I don't understand.
Moreover, I usually interact with the DOM using notations like
document.getElementById("idname");
document.getElementByTagName("tagname");
etc ect
I see that some of these DOM interfaces have names that I already know, like "Document" or "Window", I use them (like in the previous two lines of code) but I use them not capitalized ("document" rather than "Document"). I don't understand if there is a link beetwen "document" and "Document", for example...
Finally, I noticed that querying for the global object (in the browser console, for example, simply typing the keyword "this") I have in response an object that (I guess) contains all the properties and functions (or methods) of the global object. And among them there are also functions that have the same names listed in the DOM interfaces list. And that's simply another thing that I noticed that I'm not able to explain.
So, can you help me to understand more deeply DOM API?

Those things arise from an interaction of javascript and the DOM specifications.
The capital-letter Window and Document are interfaces defined by the DOM and HTML specs.
In Javascript, when executed in a browser environment, an instance of Window is the global object and Window is its prototype. document and window are getter properties defined by those interfaces. Since the window is the global object (the top-level this) and variable name resolution walks up the scope chain and finally lands at the global object if it cannot find it elsewhere window will eventually resolve to <global object>.window. Which is the attribute defined on the Window interface, which returns the window instance itself, which also is the global object. It is self-referential.
So the global object ends up having properties defined by javascript, by the dom/html specs and inherited from the prototypes also defined by those various specs.
Some prototypes are also exposed as named properties in the global object and not just the prototype chain of the instances. This is convenient for instanceof checks and feature detection. Some constructors are also exposed, e.g. new Image() creates a new instance of HTMLImageElement the same way document.createElement("img") would.
Additional Document instances can created via various constructors or factories such as DOMParser. Additional Window instances might be accessed through frames, the page's opener or spawned child windows.
Looking at the window object with a debugger may help.

Related

Global "window" object

The global window object stores properties specific to the environment (for example, window.innerHeight).
But if we print window to the console, we will see the properties highlighted in a different color.
These include Array, Object, and so on, although i thought they are internal objects.
I have a few questions:
What are these "implicit" properties?
Where do JS boundaries end and environment begin?
Can I refer to Array in Node.js, for example?
Thank you.
In the early days of Javascript, there was one master global symbol and everything that was available in the global scope whether it was part of the language itself or part of the browser environment was a property of that master global.
In the browser, that master global is the window object. Thus, you see many things on the window object that are available globally like the Array constructor.
I would guess that this is a side effect of that fact that Javascript was first designed to run in a browser and was not initially a completely stand-alone language with a stand-alone specification.
More recent revisions to the language specification are not adding some new things to the window object any more. For example, when you declare an ES6 class such as:
class Foo {
constructor(greeting) {
this.greeting = greeting;
}
}
You will not find Foo on the window object even though it may be globally available in the browser.
As others have said, the color difference in the debug output has to do with whether the symbols are enumerable or not which is a technical distinction on whether the property shows up in something like Object.keys() or a for/in loop. The property is still there and is accessible either way.

Why can we access window.document property without specifying window object?

As a JavaScript newcomer I see a lot of magic which isn't explained in books. For example, why can I write
document.getElementById('one');
When document is a property of window? From what I've read in books, we need to write
window.document.getElementById('one');
If document would be regular object like any object we would create by ourselves.
What allows us to omit window parent object while working with document property?
I googled this, but I couldn't find an explanation.
window is the Global object in a browser and because of the way scope works in JavaScript, the Global object will always be the last place that is searched for something. So, omitting window is OK because it will wind up being found at the end of the "scope chain".
document is a property of window and, as such, you do not need to qualify it with window for it to be found because when the browser reaches window and still hasn't found what it's looking for, it will look at the properties of window and find document there.
window represents the browser's window.
All global JavaScript objects, functions, and variables automatically become members of the window object.
document is also a property of global object and hence can be accessed as window.document or document.
For more information, you can refer here.

Why do we prepend global variables with `window.`?

In a lot of code examples I see around the internet, global variables such as innerWidth, onresize, navigator, etc., are written as window.innerWidth, window.onresize, window.navigator, respectively.
Why are some of these globals prepended with window. and others, such as document and console typically not prepended?
Edit:
I know how OOP works and that I am accessing various properties of the window object. I'm no novice to JavaScript. I'm sorry if my question may have been unclear. I have been programming in JS for years but have never questioned this convention, hence my question.
In essence, I am asking why we don't put window. before document, but we put it before innerWidth. Is it simply a matter of clarity? In theory, shouldn't I be able to reference any of the globals without the window. prefix and have no problem?
It's unfortunate but window in your browser refers to one object which represents two logically distinct concepts :
an instance of Window, an object with well defined properties like Window.innerWidth, logically mapped to your browser's window (or rather the tab, today, but that distinction is hidden from your script)
the global object to whom all global variables are attached as properties
Semantically, it's cleaner to not prefix the global variables, unrelated with the Window concept, with window..
Now note that this introduces a problem when you refer to your global specific variable like myThing : it's hard to know if you're knowingly referring to a global variable or if it's declared in some intermediate scope (or if you just forgot to declare the variable with var). which leads to a situation in which you won't use window. only for properties of the instance of Window but also for your specific global variables. Of course in practice you'll avoid global variables as much as possible.
Not prefixing with window. also has the advantage, when you forget a var declaration or a library import, to make your code fail fast in a not subtle way (which is better than failing in production in a hard to debug way) :
window.undeclaredVariable // no error, just an undefined value
undeclaredVariable // reference error
JavaScript would probably have been better with a distinction between those two concepts (something like global or root as in node).
All the global functions and variables are attached to the object activator, this object dependent of your host environment (browser, node, etc), in the browser environment the object activator is the window object, so each global function could be access with window.console, this.console or just console, I think the prepend is useful to have a more readable code.
You could access to global scoped variables without the window prepend just innerWidth.
Think of it like objects. You are trying to get the innerWidth of the window object its self. Document is the same way. You are trying to get those variables that describe the document itself instead of the window as a whole. And console is just that, a console that you console.log to for debugging. It also has its own properties.
They may be global variables, but they still belong to and describe a specific "object" that you must call on first. If that makes sense.

What does the standard (HTML5 and EcmaScript 5.1) say about extending host objects in the browser?

What do the recent standards say about extending host objects and their prototypes? E.g. is extending NodeList with a method _forEach or Document with a method _my_query properly defined?
Will I see anything I add to Object.prototype on host objects by the standard?
How do real implementations behave with respect to the relevant standards?
Note: I am not asking whether it is a good idea to extend host objects or their prototypes (although Object.defineProperty makes things a bit easier when it comes to enumerating issues).
ECMAScript 5 does not say anything about host objects' prototype chain.
This is defined in WebIDL.
Specifically, take a look at ECMAScript bindings section, which says:
Unless otherwise specified, the [[Prototype]] internal property of
objects defined in this section is the Object prototype object.
and this, from the following section:
Each ECMAScript global environment ([ECMA-262], section 10.2.3) must
have its own unique set of each of the initial objects, created before
control enters any ECMAScript execution context associated with the
environment, but after the global object for that environment is
created. The [[Prototype]]s of all initial objects in a given global
environment must come from that same global environment.
There's even an example:
iframe.appendChild instanceof Function; // Evaluates to true
Finally, Interface Prototype Object section says (emphasis mine):
The named properties object for a given interface A must have an
internal [[Prototype]] property whose value is as follows:
If A is not declared to inherit from another interface, then the value
of the internal [[Prototype]] property of A is the Array prototype
object ([ECMA-262], section 15.4.4) if the interface was declared with
[ArrayClass], or the Object prototype object otherwise
([ECMA-262], section 15.2.4).
Otherwise, A does inherit from another interface. The value of the
internal [[Prototype]] property of A is the interface prototype object
for the inherited interface.
So now if we look at DOM Level 3, and Document interface we can see that it inherits from Node interface. Node interface does not explicitly inherit from anything else, which means it inherits from Object.prototype.
This is theory :)
In practice, not all browsers follow this behavior, although most of the recent ones certainly do.
The ECMASCRIPT5 spec states :
A web server provides a different host environment for server-side
computation including objects representing requests, clients, and
files; and mechanisms to lock and share data. By using browser-side
and server-side scripting together, it is possible to distribute
computation between the client and server while providing a customised
user interface for a Web-based application.
Each Web browser and server that supports ECMAScript supplies its own host environment,
completing the ECMAScript execution environment.
I do not think it says anything else. This can be read to mean that an implementation can conform to the spec and implement the browser objects however it wants. This has been the case in the past. It does seem logical though to apply the power of the language to the external environment and I believe that all "modern" browsers now do that.
the dom/html elements have an prototype chain as follows:
HTMLElement > Element > Node > Object
hooking in anywhere in the chain where it makes the senes is probly the best bet.

What defines the availability of the DOM `document` property in the javascript global object?

I am a bit new to javascript and was trying to understand how the W3C DOM standard and javascript as defined by ECMAscript interoperate.
Specifically, as I understand it:
the ECMAscript standard defines the existence of a Global Object, which provides functions such as parseInt(string) and explicitly allows the presence of other built-in objects accessible through it, but the definition of these is left to the implementation.
The W3C DOM standard defines a set of objects and interfaces which correspond to the structure of an HTML document. One of these is the Document object (uppercase D) containing methods such as getElementById. However this specification, as far as I understand it, does not define how an instance of such an object representing the current document in a browser may be obtained.
Basically, what I am after is - where is it explicitly stated that when executing javascript in a web page, I can call document.getElementById("someId") (note lowercase d), and that the document property represents the DOM of the document in which the javascript is executing?
Is this particular detail implementation-specific. Shouldn't it be standardised somewhere? The nearest I can get is the Gecko DOM documentation which appears to imply that document and Document are equivalent. I thought javascript was case sensitive? Or am I just being really anal about interpreting these things?
Edit:
Trawling through the HTML 5 standard working draft after Jason's comment, I think the bit that captures what I'm looking for is
6.5.3.3 Creating scripts
...the user agent must run the following steps:
4. Set up the script's global object, the script's browsing context, the script's URL character encoding and the script's base URL
6.5.3.1 states of the global object that
"This is typically a Window object. In JavaScript, this corresponds to the global object."
Further, 6.1 Browsing Contexts states
"The main view through which a user primarily interacts with a user agent is the default view. The AbstractView object that represents this view must also implement the Window interface, and is referred to as the Document's Window object. WindowProxy objects forward everything to the active document's default view's Window object."
Since the AbstractView interface implements the document property as per DOM 2 Views spec, this presumably is what defines the existence of the Javascript global document property.
This is informally called "DOM level 0" and it has never been standardized, despite being stable for a decade and more.
window, document, and so on will be standardized in HTML 5 (a forthcoming W3C standard).
As for case-sensitivity: Document is the name of an interface. It's a type. document instanceof Document is true.
HTMLDocument is another interface. document instanceof HTMLDocument is true, too.
This may not help but my understanding of what you are asking says you are getting a little confused between and instance of and object and the Object itself.
When you call document.getElementById("someId") you are making a call to the instantiated object named document which is an instance of the object Document. This is such that if you execute document instanceof Document it will return true.
I don't know if the standard states that a browser will create an instance of the Document element or when it does though as I have never read the spec.

Categories

Resources