JavaScript:循环遍历从getElementsByTagName返回的所有元素

时间:2013-10-11 18:15:41

标签: javascript arrays foreach getelementsbytagname

我正在尝试使用forEach遍历从getElementsByTagName("input")返回的所有元素。任何想法为什么这在FF,Chrome或IE中不起作用?

<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");
            alert(input.length);
            input.forEach(ShowResults);
    </script>
    </body>
</html>

10 个答案:

答案 0 :(得分:64)

您需要将nodelist转换为数组:

<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>

或用于循环。

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

并将ShowResults函数更改为:

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

答案 1 :(得分:32)

是的,ES6:

udf

MDN Doc for Spread Operator (...)

答案 2 :(得分:8)

因为input不是数组,所以HTMLCollection 使用for循环会更好。

由于HTMLCollection是类似于数组的对象,因此您可以像call Array#forEach一样

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

答案 3 :(得分:5)

因为输入是html集合。 html集合没有forEach。

您可以通过Array.prototype.slice轻松将其转换为数组

示例:

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/

答案 4 :(得分:4)

原因是,这不起作用是因为&#39; getElementsByTagName &#39;返回一个数组 - 比如Object而不是实际的数组。如果您不知道,请参阅以下两者: -

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

因此,由于类似数组的对象继承自&#39; Object.prototype &#39;而不是&#39; Array.prototype &#39;,这意味着类似数组的对象无法访问常见的数组原型方法,如forEach(),push(),map() ,filter()和slice()。

希望有所帮助!

答案 5 :(得分:2)

HTMLCollections与数组的方法不同。您可以在浏览器的javascript控制台中查看此内容来检查此内容。

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

如果true(在本例中)有一个名为elements的方法,则控制台将返回forEach

答案 6 :(得分:2)

getElementsByTagName返回不具有HTMLCollection方法的forEach。但是,有一个简单的调整,可让您使用forEach 进行迭代,而无需创建中间数组:请使用querySelectorAllquerySelectorAll返回一个NodeList,现代浏览器有一个NodeList.prototype.forEach方法:

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

使用querySelectorAll的另一个好处是,它接受逗号分隔的查询字符串,它比标记名更灵活,更精确。例如,查询字符串

.container1 > span, .container2 > span

将仅匹配span类元素的子类container1container2

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>

如果您想在没有内置方法的古老浏览器上使用NodeList.prototype.forEach,只需添加一个polyfill。以下代码段适用于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>

答案 7 :(得分:1)

在ES6中,您可以使用spread运算符将HtmlCollection转换为数组。看到这个问题Why can't I use Array.forEach on a collection of Javascript elements?

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

答案 8 :(得分:1)

我这样做了:

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

现在,您可以在每个HTMLCollection上使用地图。

document.getElementsByTagName("input").map(
    input => console.log(input)
);

答案 9 :(得分:0)

如果可以使用ES2015,则可以使用<ul> <li><a href="/pic2_elephant"><img id="pic2" src="pic2.jpg" /> <h2>Elephant</h2></a></li> <li><a href="/pic1_dog"><<img id="pic1" src="pic1.jpg" /> <h2>Dog</h2></li> <li><a href="/pic3_cat"><<img id="pic3" src="pic3.jpg" /> <h2>Cat</h2></li> </ul> Array.from()返回的HTMLCollection转换为实数组。如果将第11行更改为以下内容,其余代码将按原样工作:

getElementsByTagName()