在nodeList上调用forEach

时间:2015-07-10 10:06:10

标签: javascript arrays foreach nodelist

我使用forEach循环遍历nodeList。我的代码如下

var array = document.querySelectorAll('items');

array.forEach(function (item) {
    console.log(item);
}); 

此代码抛出错误

  

未捕获的TypeError:array.forEach不是函数

然后在阅读了几篇在线博客文章后,我将代码改为此。

[].forEach.call(array, (function (item) {
    console.log(item);
})); 

有人可以解释为什么不能在nodeList上调用forEach以及上面的第二个代码片做了什么。 :)

修改: 7/25/2017

此问题对现代浏览器无效。您可以在其中的节点列表中使用forEach

  

虽然NodeList不是数组,但可以迭代它   使用forEach()。它也可以使用转换为数组   Array.from()。

     

然而,一些较旧的浏览器尚未实现   NodeList.forEach()和Array.from()。但这些限制可以   通过使用Array.prototype.forEach()来规避(更多内容   文件)。

参考:MDN

3 个答案:

答案 0 :(得分:9)

这是JavaScript中的一个基本内容:您可以从一个对象获取一个函数,并将 apply 应用于任何其他对象。即:将this设置为您应用该函数的对象来调用它。这是可能的,因为在JavaScript中,所有属性名称等(明确地说)都是通过名称来标识的。因此,尽管NodeList.lengthArray.length不同,但Array.forEach函数可以应用到任何公开属性length的东西(和forEach的其他内容1}}要求)。

那么在你的情况下会发生什么:

  • querySelectorAll()返回 NodeList 类型的对象,该对象恰好公开length属性并且是可枚举的(让我们说{{1}可以访问它} operator); NodeList 不会公开[]函数(正如您所见:https://developer.mozilla.org/en-US/docs/Web/API/NodeList) - 这就是为什么它无法调用forEach }直接在forEach
  • 的结果上
  • querySelectorAll()返回一个函数 - 这是{em>不那么聪明的 [].forEach
  • 的快捷方式
  • Array.prototype.forEach此函数应用到由[].forEach.call(array, …)引用的对象上,该对象类型为 NodeList (即{{1}在函数体中调用array作为forEach,因此当arraythisforEach引用this.length length尽管array {1}} NodeList 而不是真正的数组
  • 这样可行,因为array正在使用 Array NodeList 共有的属性;如果forEach想要使用 Array 具有的某些属性,但 NodeList 没有
  • ,则会失败

答案 1 :(得分:4)

NodeList对象不包含方法forEach,它是Array object的方法。以下代码:

[].forEach.call(array, (function (item) {
    console.log(item);
})); 

正在使用数组中的forEach方法并将其传递给NodeList

您拥有的另一个选项,也就是说更好,可以将您的NodeList转换为数组,如下所示:

var myArrayOfNodes = [].slice.call(NodeList);

这使用Array对象slice methodNodeList创建节点数组。这是一个更好的方法,因为你可以使用数组而不是黑客攻击类似数组的对象

答案 2 :(得分:-1)

querySelectorAll获取array-like对象中的元素而不是数组。所以你需要在第二个代码示例中使用它。