为什么不能'对Javascript元素集合执行forEach操作

Why can't I use Array.forEach on a collection of Javascript elements?

本文关键字:集合 元素 执行 forEach 操作 Javascript 不能 为什么      更新时间:2023-09-26

我正在用Babel/ES6构建一个应用程序。我想禁用它的视图版本的所有表单元素,所以我这样做:

let form = document.getElementById('application-form')
let elements = form.elements

我希望能够做到这一点,而不是使用常规的旧for循环(它确实工作):

elements.forEach((el) => {
    el.disabled = true
})

但是我得到了TypeError: elements.forEach is not a function

奇怪的是,如果我console.log(elements)在Chrome开发控制台它完全像一个数组与一堆input对象。它不显示对象的Object符号,并且所有的键都是整数。我认为它是某种伪数组,但我甚至不知道如何找到它。

EDIT:简短的回答它不是一个数组它是一个HTMLCollection。参见为什么nodelist没有forEach?


*更新*

根据这个答案,nodelist现在有forEach方法!

可以。你只是不能像使用那样使用它,因为form.elements给你的HTMLFormControlsCollection上没有forEach属性(这不是一个数组)。

你可以这样使用它:

Array.prototype.forEach.call(form.elements, (element) => {
    // ...
});

或者在现代浏览器上,你可以利用底层的HTMLCollection可迭代的这个事实,即使它没有forEach:

// `for-of`:
for (const element of elements) {
    // ...do something with `element`...
}
// Spreading into an array:
[...elements].forEach((element) => {
    // ...do something with `element`...
});

这在IE11等过时的浏览器上不起作用。

还有Array.from(需要一个过时的浏览器填充):

Array.from(elements).forEach((element) => {
    // ...
});

详情请参阅我的回答" arraylike "部分

不能HMTLCollection上使用forEachforEach只能在array上使用。

替代方法是,使用lodash和执行_.toArray(),这将把htmlcollection转换为数组。在此之后,您可以对它执行普通的数组操作。或者,使用ES6的spreadforEach()

像这样,

var a = document.getElementsByTagName('div')
[...a].forEach()

form.elements, document.getElementsByTagName, document.getElementsByClassName, document.querySelectorAll返回节点列表

节点列表本质上是一个对象,它不像数组那样有任何方法。

如果您希望使用节点列表作为数组,您可以使用Array.from(NodeList)Array.prototype.slice.call(NodeList)的老式方式

// es6
const thingsNodeList = document.querySelectorAll('.thing')
const thingsArray = Array.from(thingsNodeList)
thingsArray.forEach(thing => console.log(thing.innerHTML))
// es5
var oldThingsNodeList = document.getElementsByClassName('thing')
var oldThingsArray = Array.prototype.slice.call(oldThingsNodeList)
thingsArray.forEach(function(thing){ 
  console.log(thing.innerHTML) 
})
<div class="thing">one</div>
<div class="thing">two</div>
<div class="thing">three</div>
<div class="thing">four</div>