2

So let's say I have an array of DOM elements:

var z = document.getElementsByClassName('name');

and for each element I want to set attribute with for in loop:

for(var n in z){z[n].setAttribute('marked', '1');}

For above code I get z[n].setAttibute is not a function. However when I manually check in console elements of z array, marked attribute has been added to each element. Why is that happening and how can I prevent such error from happening?

3
  • n is the element, not an index, do n.setAttribute. You should use a traditional counter for for a nodelist Commented Jul 3, 2016 at 20:46
  • 2
    A nodelist is array-like, using a regular for-loop is probably more appropriate. Commented Jul 3, 2016 at 20:48
  • See Why is using “for…in” with array iteration a bad idea? Commented Jul 3, 2016 at 21:28

2 Answers 2

4

document.getElementsByClassName returns an instance of HTMLCollection, an array-like object. for..in loop was designed for objects, not arrays. It iterates through all properties of an object. Therefore, when iterating through HTMLCollection, besides array indexes you get also other properties, like length. As length is simply a number, it doesn't have setAttribute method, so you get that error.

You should either use a regular for loop, or for..of loop:

const z = document.getElementsByClassName('name')

// Regular loop:
for (let i = 0, len = z.length; i < len; i++) {
  z[i].setAttribute('marked', '1')
}

// for..of loop:
for (const element of z) {
  element.setAttribute('marked', '1')
}

You can also convert HTMLCollection to array using Array.from(). Then you can use all array methods on it, for example .forEach():

const z = Array.from(document.getElementsByClassName('name'))

z.forEach(element=> element.setAttribute('marked', '1'))
Sign up to request clarification or add additional context in comments.

1 Comment

getElementsByClassName returns a HTMLCollection, not a NodeList. The difference is relevant because DOM4 made NodeList iterable, so you can use forEach directly.
0
[].forEach.call(z, function(el) {
 el.setAttribute('marked', '1');
})

for..in will get all the keys of the HTMLCollection, including the property .length. .length is a Number and doesn't have a .setAttribute function.

Comments

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.