如何遍历从 getElementsByTagName 返回的所有元素

IT技术 javascript arrays foreach getelementsbytagname
2021-01-29 03:30:02

我正在尝试遍历从getElementsByTagName("input")使用 forEach返回的所有元素任何想法为什么这在 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>
6个回答

您需要使用以下命令将节点列表转换为数组:

<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 循环。

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

并将 ShowResults 函数更改为:

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

为什么我们需要这样做?
JavaScript 中的一些对象看起来像一个数组,但它们不是一个。这通常意味着它们具有索引访问和长度属性,但没有任何数组方法。示例包括特殊变量参数、DOM 节点列表和字符串。类数组对象和通用方法提供了使用类数组对象的技巧。 来源

2019 年 10 月 7 日更新,
现在可以使用 ES6 [...inputList].forEach,或者Array.from(inputList)

我想你忘记let i了 for 循环。
2021-03-13 03:30:02
我在表单上有 > 1000 个隐藏的输入字段。在这种情况下,哪个选项最有效?
2021-03-15 03:30:02
2021-03-20 03:30:02
他们俩一模一样。随意使用任何你想要的。
2021-03-21 03:30:02
因为Array.prototype.slice.call(input)你可以使用简写[].slice.call(input)
2021-04-07 03:30:02

是的,ES6:

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

扩展运算符的 MDN 文档 ( ...)

现在在 ES6 中,您可以forEach用于 NodeList,但不能用于 HTMLCollection。getElementsByTagName返回 HTMLCollection,而querySelectorAll返回 NodeList。
2021-04-05 03:30:02

getElementsByTagName返回一个HTMLCollection,它没有forEach方法。但是,有一个简单的调整可以让您在forEach 创建中间数组的情况下进行迭代querySelectorAll改为使用querySelectorAll返回 a NodeList,现代浏览器有一个NodeList.prototype.forEach方法:

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

使用的另一个好处querySelectorAll是它接受逗号分隔的CSS 选择器,这比标签名称更加灵活和精确。例如,选择器

.container1 > span, .container2 > span

将只匹配span属于container1类元素的子元素的 s 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>

如果你想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>

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

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

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

原因,这不起作用是因为“ getElementsByTagName ”返回一个数组 - 像 Object 而不是实际的数组。如果您不知道,以下是它们的外观:-

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

因此,由于类数组对象继承自“ Object.prototype ”而不是“ Array.prototype ”,这意味着类数组对象无法访问常见的数组原型方法,如 forEach()、push()、map()、过滤器()和切片()。

希望有帮助!

这是一个很好的解释
2021-04-02 03:30:02