Elegant way around HTMLCollections updating dynamically

别说谁变了你拦得住时间么 提交于 2019-12-25 01:58:00

问题


Today, I discovered something in Javascript that looked like "strange behavior" to me. Let's assume the following minimal example:

HTML:

<div id="test">
    <span>1</span>
    <span>2</span>
</div>

JS:

var div   = document.getElementById('test');
var spans = div.getElementsByTagName('span');
div.removeChild(spans[0]);
div.removeChild(spans[1]);

(Fiddle: http://jsfiddle.net/SkYJg/)

Now, when running the script, I get an error:

TypeError: Argument 1 of Node.removeChild is not an object.

Looking closer, it turned out that spans[1] is null after the first one was removed. And indeed, the following code

var div   = document.getElementById('test');
var spans = div.getElementsByTagName('span');
console.log(spans.length);
div.removeChild(spans[0]);
console.log(spans.length);
div.removeChild(spans[1]);

yields 2at the first log operation, but 1 the second time.

Now, it's pretty clear what happens here: after the first ?span? was removed from DOM, it's not part fo that HTMLCollection stored inside spans anymore either.

I always was under the impression, that the HTMLCollection-Object holds references to all objects that it contains. I didn't modify the collection anywhere after creating it. So I thought (but it was wrong, obviously) that the collection would behave like an array: references stay there until I delete/modify them manually.

I looked into the specification at MDN. And, indeed, richt at the top it says: HTMLCollections in the HTML DOM are live; they are automatically updated when the underlying document is changed.

The only way I could think of to prevent this is to loop over the collectino before doing anything with it, copying all references to an array, and use the array to access them afterwards. But that just looks so horribly bulky to me... is there a nicer solution? Like some way to make the collection static or to copy it without looping?

(in the minimal example I could just remove spans[0] twice, of course, but it isn't that simple in reality).

[Edit]: After seeing @Teemu's answer, I repeat: it's NOT that simple in my real code (that one is just too complex to show it here completely). I assure you, I really need random access to all elements that were inside that Collection, deleted or not.


回答1:


A back-gate would be to use querySelectorAll() instead of getElementsByTagName(), it returns a non-live NodeList.




回答2:


You're not using a "reference" when trying to remove the tag, just pointing the first or the second element of a collection. To use reference, you should create tags with ID and than point it by ID. The key of an Array is a third part, that's why it will be updated.

On the other hand, is a fact that JavaScript is objected-oriented sometimes, and other times it is just a script.



来源:https://stackoverflow.com/questions/21835282/elegant-way-around-htmlcollections-updating-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!