Javascript 为什么不可能在节点列表上调用forEach?
我使用forEach循环遍历节点列表。我的代码如下Javascript 为什么不可能在节点列表上调用forEach?,javascript,arrays,foreach,nodelist,Javascript,Arrays,Foreach,Nodelist,我使用forEach循环遍历节点列表。我的代码如下 var array = document.querySelectorAll('items'); array.forEach(function (item) { console.log(item); }); 这段代码会抛出一个错误 未捕获类型错误:array.forEach不是函数 在阅读了几篇在线博客文章后,我将代码改为这样 [].forEach.call(array, (function (item) { console
var array = document.querySelectorAll('items');
array.forEach(function (item) {
console.log(item);
});
这段代码会抛出一个错误
未捕获类型错误:array.forEach不是函数
在阅读了几篇在线博客文章后,我将代码改为这样
[].forEach.call(array, (function (item) {
console.log(item);
}));
有人能解释一下为什么不能在节点列表上调用forEach,以及上面的第二个代码段的作用是什么吗
编辑:2017年7月25日
这个问题对现代浏览器无效。可以对其中的节点列表使用forEach
虽然NodeList不是数组,但可以对其进行迭代
使用forEach()。还可以使用以下命令将其转换为数组:
数组。from()
但是,一些较旧的浏览器尚未实现
NodeList.forEach()或Array.from()。但这些局限性可能是有限的
通过使用Array.prototype.forEach()避免了此问题(本文将详细介绍
文件)
Ref:节点列表对象不包含方法
forEach
,它是。以下代码:
[].forEach.call(array, (function (item) {
console.log(item);
}));
正在使用数组中的forEach
方法并向其传递NodeList
还有一个更好的选择是将节点列表
转换为数组,如下所示:
var myArrayOfNodes = [].slice.call(NodeList);
这将使用数组对象
切片
从节点列表
创建节点数组。这是一种更好的方法,因为您可以使用数组,而不是攻击类似数组的对象querySelectorAll
获取类似数组的对象中的元素,而不是数组。因此,您需要使用第二个代码示例中的函数。这是JavaScript中的一个基本内容:您可以从一个对象获取函数并应用于任何其他对象。也就是说:使用将此设置为应用函数的对象来调用它。这是可能的,因为在JavaScript中,所有属性名等(简单地说)都由名称标识。因此,尽管NodeList.length
与Array.length
不同,函数Array.forEach
可以应用于任何公开属性length
的内容(以及forEach
所需的其他内容)
因此,在您的案例中发生的情况是:
querySelectorAll()
返回类型为NodeList的对象,该对象恰好公开了length
属性,并且是可枚举的(假设它可由[]
运算符访问);NodeList不公开forEach
函数(如您所见,即:)-这就是为什么不可能直接对queryselectoral()的结果调用forEach
[].forEach
返回一个函数-对于数组.prototype.forEach
- 使用
[].forEach.call(array,…)
此函数应用于array
引用的对象,即NodeList类型的对象(也就是说,forEach
在函数体中被array
作为this
调用,所以在forEach
中有this.length
它指的是array
中的length
,尽管array
是节点列表而不是实数组)
- 这是可行的,因为
forEach
正在使用数组和NodeList共同拥有的属性;如果forEach
想要使用数组拥有的某个属性,而NodeList没有,它将失败
对不起,你的意思是什么?正如你指出的,querySelectorAll
的返回值不返回数组
,因此我们不能显式调用.forEach
。但是,我们可以通过将它传递到forEach
来避免键入它来完成任务。术语可能不同,但我猜它可能是一个duck键入。检查并尝试此单线节点列表修补程序,您可以在NodeList
上使用forEach