forEach 不是 JavaScript 数组的函数错误

forEach is not a function error with JavaScript array

我正在尝试做一个简单的循环:

const parent = this.el.parentElement
console.log(parent.children)
parent.children.forEach(child => {
  console.log(child)
})

但我收到以下错误:

VM384:53 Uncaught TypeError: parent.children.forEach is not a function

即使 parent.children 记录:

可能是什么问题?

注:这里是 JSFiddle.

parent.children 是一个 HTMLCollection 类数组对象。首先,您必须将其转换为真正的 Array 才能使用 Array.prototype 方法。

const parent = this.el.parentElement
console.log(parent.children)
[].slice.call(parent.children).forEach(child => {
  console.log(child)
})

parent.children 不是数组。它是 HTMLCollection,它没有 forEach 方法。您可以先将其转换为数组。例如在 ES6 中:

Array.from(parent.children).forEach(child => {
    console.log(child)
});

或使用扩展运算符:

[...parent.children].forEach(function (child) {
    console.log(child)
});

parent.children 将 return 一个 节点列表 列表,技术上是 html Collection。这是一个类似于对象的数组,但不是数组,因此您不能直接在其上调用数组函数。在这种情况下,您可以使用 Array.from() 将其转换为真正的数组,

Array.from(parent.children).forEach(child => {
  console.log(child)
})

那是因为parent.children是一个NodeList,它不支持.forEach方法(因为NodeList是类数组结构但不是数组),所以尝试首先使用

将其转换为数组来调用它
var children = [].slice.call(parent.children);
children.forEach(yourFunc);

第一个选项:间接调用 forEach

parent.children 是一个类似数组的对象。使用以下解决方案:

const parent = this.el.parentElement;

Array.prototype.forEach.call(parent.children, child => {
  console.log(child)
});

parent.childrenNodeList类型,它是一个类数组对象,因为:

  • 其中包含length属性,表示节点数
  • 每个节点都是一个属性值,名称为数字,从0开始:{0: NodeObject, 1: NodeObject, length: 2, ...}

this article 中查看更多详细信息。


第二个选项:使用可迭代协议

parent.children 是一个 HTMLCollection:它实现了 iterable protocol。在 ES2015 环境中,您可以将 HTMLCollection 与任何接受迭代的构造一起使用。

HTMLCollection 与扩展运算符一起使用:

const parent = this.el.parentElement;

[...parent.children].forEach(child => {
  console.log(child);
});

或者使用 for..of 循环(这是我的首选):

const parent = this.el.parentElement;

for (const child of parent.children) {
  console.log(child);
}

一个更天真的版本,至少你确定它可以在所有设备上运行,无需转换和 ES6 :

const children = parent.children;
for (var i = 0; i < children.length; i++){
    console.log(children[i]);
}

https://jsfiddle.net/swb12kqn/5/

不需要 forEach,您可以仅使用 from 的第二个参数进行迭代,如下所示:

let nodeList = [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]
Array.from(nodeList, child => {
  console.log(child)
});

因为您使用的是 ES6 的功能(arrow functions), you may also simply use a for loop 像这样:

for(let child of [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]) {
  console.log(child)
}

如果您尝试像这样循环 NodeList

const allParagraphs = document.querySelectorAll("p");

我强烈推荐这样循环:

Array.prototype.forEach.call(allParagraphs , function(el) {
    // Write your code here
})

就我个人而言,我尝试了几种方法,但大多数都没有用,因为我想循环 NodeList,但这个方法很有效,试试吧!

NodeList不是一个数组,但是我们把它当作一个数组,使用Array. 所以,你需要知道它在旧浏览器中是不支持的!

需要有关 NodeList 的更多信息?请阅读其documentation on MDN.

您可以使用childNodes代替children,考虑到浏览器兼容性问题,childNodes也更可靠,更多信息here

parent.childNodes.forEach(function (child) {
    console.log(child)
});

或使用扩展运算符:

[...parent.children].forEach(function (child) {
    console.log(child)
});

你可以检查你输入的 forEach 是否正确,如果你像在其他编程语言中那样输入 foreach 它就不会工作。

使用JSON.parse()

str_json = JSON.parse(array);
str_json.forEach(function (item, index) {
    console.log(item);
});