2

I am new to javascript and am learning arrays and loops. I was writing some basic code to change classes of some paragraphs, but am unable to do so. Can anyone tell me what am I doing wrong in it?

function change() {
  var x = document.getElementsByClassName('a');
  x[0].className = 'b';
  for (var y = 0; y < x.length; y++) {
    console.log(x[y]);
    x[y].className = "b";
  }
}
p.a {
  font-size: 2em;
  color: red;
  text-align: center;
}

p.b {
  font-size: 1em;
  color: green;
  text-align: center;
}
<p class='a'>a</p>
<p class='a'> b</p>
<p class='a'>c</p>
<p class='a'>a</p>
<p class='a'>b</p>
<p class='a'>c</p>
<p class='a'>a</p>
<p class='a'>b</p>
<p class='a'>c</p>

<button onclick="change()">Change</button>

As it turns out some paragraphs are changing and some are not can anyone tell what am I doing wrong?

2
  • Well, which ones are not changing? Do they have anything in common at the time? Commented Oct 26, 2019 at 20:58
  • 1
    getElementsByClassName() returns a live node collection. Since as you change the classes, those elements are removed from the collection. Commented Oct 26, 2019 at 21:04

1 Answer 1

3

document.getElementsByClassName() is a live collection which means as you loop through the elements and change the class you are changing the collection. It's almost always a bad idea to alter the membership of a collection while you iterate over it. This makes your indexes point to the wrong elements. The easiest solution is to use querySelectorAll() instead.

function change() {
  var x = document.querySelectorAll('.a');
  for (var y = 0; y < x.length; y++) {
    x[y].className = "b";
  }
}
p.a {
  font-size: 2em;
  color: red;
  text-align: center;
}

p.b {
  font-size: 1em;
  color: green;
  text-align: center;
}
<p class='a'>a</p>
<p class='a'> b</p>
<p class='a'>c</p>
<p class='a'>a</p>
<p class='a'>b</p>
<p class='a'>c</p>
<p class='a'>a</p>
<p class='a'>b</p>
<p class='a'>c</p>

<button onclick="change()">Change</button>

Sign up to request clarification or add additional context in comments.

3 Comments

Can also use [...x] to convert the collection to a plain old array. Variable names could also be clearer.
as getELementByClassName is a live collection, shouldn't my code work if i change - x[y].className = "b"; by x[0].className = "b"; so that no matter how many times the collection change always the 1st element in the array will change? But still it doesnt change all the elements?
No, it doesn’t change them all @DeekshantWadhwa. But notice that it doesn’t skip any. As you change them, the length of of x decreases so you never make it all the way through. Try capturing the length of x outside the loop and try again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.