Home > Enterprise >  Why is parentNode defunct in the javascript DOM for Attr (Node.ATTRIBUTE_NODE)?
Why is parentNode defunct in the javascript DOM for Attr (Node.ATTRIBUTE_NODE)?

Time:10-28

In the javascript DOM, the class Attr extends Node, of nodeType == Node.ATTRIBUTE_NODE. This is great. The Node.prototype has the parentNode property, which is some getter "get parentNode" function with body I cannot inspect (on Chrome). But for Attr the parentNode always returns null, and it cannot be assigned either.

I would like to know why that is? Did they expect that Attr objects would be reused and shared between different nodes?

Here I am showing a Chrome console dialog:

$0
    <section code=​"123" foo=​"bar">​…​</section>​
$0.attributes[0]
    code=​"123"
$0.attributes[0].parentNode
    null
$0.attributes[0].parentNode = $0
    <section code=​"123" foo=​"bar">​…​</section>​
$0.attributes[0].parentNode
    null
Object.defineProperty(Attr.prototype, 'parentNode', { writable: true, value: null });
    Attr {…}
$0.attributes[0].parentNode
    null
$0.attributes[0].parentNode = $0
    <section code=​"123" foo=​"bar">​…​</section>​
$0.attributes[0].parentNode
    <section code=​"123" foo=​"bar">​…​</section>​

Now whether attributes are reused?

s = $0.cloneNode(false)
    <section code=​"123" foo=​"bar">​</section>​
s.attributes[0] == $0.attributes[0]
    false
s.attributes.removeNamedItem('code')
    code=​"123"
s.attributes.removeNamedItem('foo')
    foo=​"bar"
s
    <section>​</section>​
s.attributes.setNamedItem($0.attributes[0])
    Uncaught DOMException: Failed to execute 'setNamedItem' on 'NamedNodeMap': The node provided is an attribute node that is already an attribute of another Element; attribute nodes must be explicitly cloned.

s.attributes.setNamedItem($0.attributes[0].cloneNode())
    null
s
    <section code=​"123">​</section>​

So it seems clear that Attr is not supposed to be shared between different elements. Therefore, I don't understand why parentNode property was decided to leave defunct for Attr nodes?

I can probably make my own workarounds, by overriding the Node property with one specific for Attr, but still, why?

What to know a use-case? Well, how about implementing XSLT on javascript, in XSLT you can inquire the parent of an attribute, which is often quite important.

CodePudding user response:

According to the specification:

Note:

Attr nodes participate in a tree for historical reasons; they never have a (non-null) parent or any children and are therefore alone in a tree.

So, Chrome is following spec there. Attr elements never have a non-null parentNode.

It's always dangerous to ask "why" questions because without being able to cite the specific meeting notes where a decision is made, the answer is going to be a matter of opinion.

But the DOM spec is clear that the original design of Attr was a mistake, for instance:

Attr nodes are simply known as attributes. They are sometimes referred to as content attributes to avoid confusion with IDL attributes.

Attributes have a namespace (null or a non-empty string), namespace prefix (null or a non-empty string), local name (a non-empty string), value (a string), and element (null or an element).

Note:

If designed today they would just have a name and value. ☹

This seems to be just one way in which the design doesn't necessarily make great sense.

CodePudding user response:

Actually, I was just trying to figure out how I can fix this design mistake. And I found on Chrome that there is (now?) the Attr.prototype.ownerElement property. Why that isn't simply parentElement (or parentNode), is probably another indicator that the DOM specification was sloppily thrown together and perhaps the people involved didn't really know what they were doing.

So in short the functionality exists, they just gave that a different name.

  • Related