最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - classList.remove is removing elements from a HTMLCollection? - Stack Overflow

programmeradmin2浏览0评论

I'm encountering some very strange behaviour with JavaScripts new classList API, say we have the following HTML code:

<p class="testing">Lorem Ipsum</p>
<p class="testing">Lorem Ipsum</p>

And the following JavaScript code:

var elements = document.getElementsByClassName("testing");
alert(elements.length);
elements[0].classList.remove("testing");
alert(elements.length);

The first alert will give you a value of 2, whilst the second alert returns 1.

It appears that removing the class from the element is also removing it from the elements HTMLCollection, which makes absolutely no sense to me.

You can see an example of this code HERE.

I encountered this problem when trying to remove a certain class from some elements using code like below:

var elements = document.getElementsByClassName('testing');
var elementsLength = elements.length - 1;
for(var i = 0; i <= elementsLength ; i++)
{
    elements[i].classList.remove('testing');
}

Say we have two elements like in the example above, the loop runs successfully the first time, but the second time it's looking for an element in the HTMLCollection that no longer exists, so I get something like "TypeError: elements[i] is undefined".

You can see an example of the above code HERE

This is frustrating to say the least, I can't understand why/how classList.remove could effect what is effectively an array set only once before the classList.remove function is called. I can't even seem to find anything about this behaviour online.

Am I doing something crazy? Or has I unearthed some strange hidden feature of the classList api that no one knows about?

I'm encountering some very strange behaviour with JavaScripts new classList API, say we have the following HTML code:

<p class="testing">Lorem Ipsum</p>
<p class="testing">Lorem Ipsum</p>

And the following JavaScript code:

var elements = document.getElementsByClassName("testing");
alert(elements.length);
elements[0].classList.remove("testing");
alert(elements.length);

The first alert will give you a value of 2, whilst the second alert returns 1.

It appears that removing the class from the element is also removing it from the elements HTMLCollection, which makes absolutely no sense to me.

You can see an example of this code HERE.

I encountered this problem when trying to remove a certain class from some elements using code like below:

var elements = document.getElementsByClassName('testing');
var elementsLength = elements.length - 1;
for(var i = 0; i <= elementsLength ; i++)
{
    elements[i].classList.remove('testing');
}

Say we have two elements like in the example above, the loop runs successfully the first time, but the second time it's looking for an element in the HTMLCollection that no longer exists, so I get something like "TypeError: elements[i] is undefined".

You can see an example of the above code HERE

This is frustrating to say the least, I can't understand why/how classList.remove could effect what is effectively an array set only once before the classList.remove function is called. I can't even seem to find anything about this behaviour online.

Am I doing something crazy? Or has I unearthed some strange hidden feature of the classList api that no one knows about?

Share Improve this question edited Mar 1, 2014 at 0:16 Sean asked Mar 1, 2014 at 0:06 SeanSean 6,4999 gold badges49 silver badges70 bronze badges 1
  • It's good that you cached the .length property in elementsLength for the loop. With a normal array this is good practice and will give you a small speed boost, but with a HTMLCollection it is particularly important for performance due to it's "live" nature. – Useless Code Commented Mar 1, 2014 at 10:05
Add a comment  | 

2 Answers 2

Reset to default 15

The collection returned by document.getElementsByClassName is live so if an element doesn't have that class anymore it will be removed from the collection.

You can either create a non-live copy of the collection:

var elements = [].slice.call(document.getElementsByClassName('testing'));

Or take in account that it's live:

while (elements.length) elements[0].classList.remove('element-focus');

Using document.getElementsByClassName returns a live HTMLCollection:

An HTMLCollection in the HTML DOM is live; it is automatically updated when the underlying document is changed.

Thus (as described in plalx's answer) if you remove an element's class, the element is removed from an HTMLCollection based on that class.

Instead you could use document.querySelectorAll which returns a static NodeList collection:

The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.

So your code would change from

var elements = document.getElementsByClassName("testing");

with the class name "testing" as an argument, to

var elements = document.querySelectorAll(".testing");

with the class selector ".testing" as an argument.

And then you could iterate over elements which would be a static NodeList.

发布评论

评论列表(0)

  1. 暂无评论