I am studying the document object model implemented in JavaScript, and I understand (this according to MDN) that the Element
class/prototype is meant to represent an element of an arbitrary document, e.g. HTML, XML, or even SVG documents. In contrast, the HTMLElement
sub-class is meant to represent elements of specifically HTML documents. However, this does not seem to be totally borne out by the actual ownership of properties between the two classes.
In particular, why is the property innerHTML
, which seems to be specific to HTML documents, owned by the Element
prototype?
Object.getOwnPropertyNames(Element.prototype).includes('innerHTML')
>>> true
Object.getOwnPropertyNames(HTMLElement.prototype).includes('innerHTML')
>>> false
Similarly, I observe that the body
and head
properties are owned by Document.prototype
, rather than HTMLDocument.prototype
. This seems peculiar as I wouldn't expect all types of documents to have a head and body.
Is this just JS compatibility/legacy weirdness? (If so, I wonder if there is a story of how it came about) Or is there some logic to this property-ownership structure that I am missing?
For innerHTML
, that was not before HTML5 that it made it to the specs, it was an IE invention that got adopted by others vendors later on, before the specs caught on.
There was active discussions about renaming it or even limiting it to the HTMLElement
interface. (e.g see the note in this HTML5 draft, or this comment on a related DOM issue.)
But keeping it for MathML or even SVG elements still made sense, so they kept it as it was designed by the vendors.
For the Document case... that's an even bigger mess.
It seems that since DOM 1 the body
property wasn't on Document
but on HTMLDocument
only and head
wasn't there at all.
In DOM 3 the HTMLDocument
interface was no more part of the DOM specs and still isn't in DOM LS. It is now specced by HTML, but only so that is it an alias to the Document
interface.
It's also in the HTML specs that body
and head
are defined as an extension to the Document
interface.
This is following an attempt to merge all [XXX]Document
interfaces into Document
, while some decided to never do that, some to undo and ... well, as I said it's a mess. I guess the most up to date discussion is here. For some history you can look at this bug and this one and everything linked there.
In the facts, it seems every modern browsers now indeed kept HTMLDocument
as an alias to Document
, with no added properties:
const own_props = Object.getOwnPropertyDescriptors( HTMLDocument.prototype );
console.log( Object.keys( own_props ) ); // [ "constructor" ] => doesn't add anything to Document
Ps: (note that the DOM is usually not implemented in javascript).