0

I m storing all the elements from a getElementsByClassName to a variable, I would imagine I can foreach loop this variable to get every single ids from it. But its not working.

var el = document.getElementsByClassName("machine_btn_over_layer");
el.forEach(test);
var test = function() {
  console.log("test");
}
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>

What am I doing wrong? Im getting error saying function is not working

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
  • 2
    In the console you should have seen exactly what you were doing wrong: `"Uncaught TypeError: el.forEach is not a function"` You're using a function that doesn't exist; instead convert the live NodeList to an Array and then use `Array.prototype.forEach()`. – David Thomas Feb 20 '18 at 15:26
  • https://stackoverflow.com/questions/15843581/how-to-correctly-iterate-through-getelementsbyclassname I think this post is more relevant in this case. – GSazheniuk Feb 20 '18 at 15:30

3 Answers3

8

You need to make two changes. First document.getElementsByClassName is a HTMLCollection so array method will not work on this. So to use the array method you can convert it to array using spread operator(...)

Secondly a function declared var test = function() {} is never hoisted. So when el.forEach is called it don't get the function, hence it will throw undefined is not a function

var el = [...document.getElementsByClassName("machine_btn_over_layer")];
var test = function() {
  console.log("test");
}
el.forEach(test);
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
brk
  • 48,835
  • 10
  • 56
  • 78
  • Upvote for using (...). I've never seen that syntax before! – GSazheniuk Feb 20 '18 at 15:34
  • Doesn't work in all browsers, be careful. I'd be more inclinced to use something like Array.from() to make it into an array -- even though that also doesn't work in all browsers, at least it has polyfills. – TKoL Feb 20 '18 at 15:54
3

Use the documentation to help you! document.getElementsByClassName:

var elements = document.getElementsByClassName(names)

elements is a live HTMLCollection of found elements.

The first thing you should notice on the HTMLCollection documentation is that it does not have a method named forEach. But it does have a property named length

HTMLCollection.length

Returns the number of items in the collection.

And a method named item

HTMLCollection.item()

Returns the specific node at the given zero-based index into the list. Returns null if the index is out of range.

So you should be able to do this:

for (var i = 0; i < el.length; i++) test(el.item(i));

Or use the array sugar:

for (var i = 0; i < el.length; i++) test(el[i]);
Community
  • 1
  • 1
Chris Martin
  • 30,334
  • 10
  • 78
  • 137
-1

Not every browser implements Array.prototype methods on HTMLCollection returned by getElementsByClassName method.

Also variable assignments do not hoist. Function declarations do.

var el = document.getElementsByClassName("machine_btn_over_layer");

// manually call Array.prototype.forEach on HTMLCollection
Array.prototype.forEach.call(el, test);

// replace function expression with function declaration to hoist with value
function test() {
  console.log("test");
}
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
<div class="machine_btn_over_layer"></div>
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98