JavaScript: Loop through all the elements returned from getElementsByTagName

假装没事ソ 提交于 2019-11-26 15:28:19

You need to convert the nodelist to array with this:

<html>
    <head>
    </head>
    <body>
        <input type="text" value="" />
        <input type="text" value="" />
        <script>
            function ShowResults(value, index, ar) {
                alert(index);
            }
            var input = document.getElementsByTagName("input");
            var inputList = Array.prototype.slice.call(input);
            alert(inputList.length);
            inputList.forEach(ShowResults);
    </script>
    </body>
</html>

or use for loop.

for(i = 0;i < input.length; i++)
{
    ShowResults(input[i].value);
}

and change ShowResults function to:

function ShowResults(value) {
   alert(value);
}

Yay, ES6:

const children = [...parent.getElementsByTagName('tag')];
children.forEach((child) => { /* Do something; */ });

MDN Doc for Spread Operator (...)

grape_mao

Because input is not an array, it's HTMLCollection Use a for loop would be better.

And since HTMLCollections are array-like objects you can call Array#forEach on it like this

Array.prototype.forEach.call(input, ShowResults);
Daniel Dykszak

It's becauseinput is html collection. html collection don't have forEach.

you can easily conver it to array by Array.prototype.slice

example:

function ShowResults(value, index, ar) {
            alert(index);
        }
        var input = document.getElementsByTagName("input");
        alert(input.length);
input = Array.prototype.slice.call(input)
        input.forEach(ShowResults);

http://jsfiddle.net/fPuKt/1/

The reason, this does not work is because 'getElementsByTagName' returns an array - like Object rather than an actual array. In case you are not aware, here's how both of them look like :-

var realArray = ['a', 'b', 'c'];
var arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

Thus, since Array-like objects inherit from 'Object.prototype' instead of 'Array.prototype', this means that Array-like Objects can't access common Array prototype methods like forEach(), push(), map(), filter(), and slice().

Hope that helps!

getElementsByTagName returns an HTMLCollection, which do not have a forEach method. But, there's a simple tweak that will allow you to iterate with forEach without creating an intermediate array: use querySelectorAll instead. querySelectorAll returns a NodeList, and modern browsers have a NodeList.prototype.forEach method:

document.querySelectorAll('input')
  .forEach((input) => {
    console.log(input.value);
  });
<input type="text" value="foo">
<input type="text" value="bar">

Another benefit to using querySelectorAll is that it accepts comma-separated query strings, which are far more flexible and precise than just tag names. For example, the query string

.container1 > span, .container2 > span

will only match spans which are children of elements with a class of container1 or container2:

document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach((span) => {
    span.classList.add('highlight');
  });
.highlight {
  background-color: yellow;
}
<div class="container1">
  <span>foo</span>
  <span>bar</span>
</div>
<div class="container2">
  <span>baz</span>
</div>
<div class="container3">
  <span>buzz</span>
</div>

If you want to use NodeList.prototype.forEach on ancient browsers that do not have the method built-in, simply add a polyfill. The following snippet will work on IE11:

// Polyfill:
if (window.NodeList && !NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function(callback, thisArg) {
    thisArg = thisArg || window;
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

// Main code:
document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach(function(span) {
    span.classList.add('highlight');
  });
.highlight {
  background-color: yellow;
}
<div class="container1">
  <span>foo</span>
  <span>bar</span>
</div>
<div class="container2">
  <span>baz</span>
</div>
<div class="container3">
  <span>buzz</span>
</div>

HTMLCollections doesn't have the same methods as arrays. You can check this thing by tiping this in the javascript console of your browser.

var elements = document.getElementsByClassName('some-class');
'forEach' in elements;

And the console will return true if elements (in this case) has a method called forEach to call.

inostia

In ES6 you can use the spread operator to convert an HtmlCollection to an Array. see this question Why can't I use Array.forEach on a collection of Javascript elements?

input = [...input]
input.forEach(ShowResults)

I did this:

HTMLCollection.prototype.map = Array.prototype.map;

You can now use map on every HTMLCollection.

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