Element reference breaks on modification of innerH

2019-02-23 19:07发布

When creating elements via code, I have encountered an issue where modifying the innerHTML property of an element breaks any references to other elements that are injected into the modified element prior to the modification.

I have a test case here: http://jsfiddle.net/mJ7bF/1/ in which I would expect the link1 reference to behave exactly as link2 does.

This second test case is the same code, but instead of using the innerHTML property to add the <br> tag, I create the line break with an object. This test behaves as expected: http://jsfiddle.net/K4c9a/2/

My question is not regarding this specific code, but the concept behind it: what happens to the link1 reference in that first test case? If it doesn't refer to the HTML/DOM node that is visible when the cont node is injected into the document, what DOES it refer to, and how does this fit in with the ByReference nature of javascript objects?

2条回答
ゆ 、 Hurt°
2楼-- · 2019-02-23 19:48

few things here.

first of all. strings are immutable hence doing element.innerHTML += "<br>" acts as a complete read and rewrite.

second, why that is bad:

aside from performance, mootools (and jquery, for that matter) assigns special unique sequential uids to all referenced elements. you reference an element by calling a selector on it or creating it etc.

then consider that SPECIFIC element with uid say 5. the uid is linked to a special object called Storage that sits behind a closure (so its private). it has the uid as key.

element storage then works on a element.store("key", value") and element.retrieve("key")

and finally, why that matters: events are stored into element storage (eg, Storage[5]['events']) - do element.retrieve("events") and explore that in fireBug if you're curious.

when you rewrite the innerHTML the old element stops existing. it is then recreated but the event handler AND the reference to the function that you bound earlier will no longer work as it will now get a NEW uid.

that's about it, hope it makes sense.

to add a br just do new Element("br").inject(element) instead or create a templated fragment for the lot (fastest) and add in 1 big chunk, adding events after.

查看更多
看我几分像从前
3楼-- · 2019-02-23 20:07

HTML is represented internally by a DOM object structure. Kind of like a Tree class in traditional programming languages. If you set innerHTML, the previous nodes in the parent node are destroyed, the new innerHTML is parsed, and new objects are created. The references are no longer the same.

div
|-- a..

The div object above contains an Anchor object as a child. Now set a variable link1 as a reference to the address of this Anchor object. Then the .innerHTML is += "<br />", which means all of the nodes of div are removed, and recreated dynamically based on the parsed result of the new value of .innerHTML. Now the old reference is no longer valid because the Anchor tag was re-created as a new object instance.

查看更多
登录 后发表回答